# 这是一个示例 Python 脚本。

# 按 Shift+F10 执行或将其替换为您的代码。
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。

import sys
import os
import re
import json
import time
import shutil
import subprocess
import tempfile
import webbrowser
import warnings
from datetime import datetime
import fitz  # PyMuPDF
import chardet
import ebooklib
import ebooklib.epub
from PIL import Image, ImageOps, ImageEnhance
from bs4 import BeautifulSoup
import markdown
from pygments import highlight
from pygments.lexers import get_lexer_for_filename, TextLexer
from pygments.formatters import HtmlFormatter

from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                           QLabel, QPushButton, QTextEdit, QFileDialog, QMessageBox,
                           QMenu, QToolBar, QStatusBar, QScrollArea, QComboBox, QSlider, 
                           QMenuBar, QListWidget, QListWidgetItem, QCheckBox, QDialog,
                           QListView, QSplitter, QFrame, QTabWidget, QGraphicsBlurEffect,
                           QLineEdit, QButtonGroup, QRadioButton, QSpinBox)
from PyQt6.QtCore import Qt, QUrl, QEvent, QPointF, QTimer, QSize, QCoreApplication, QRectF, QPoint
from PyQt6.QtGui import (QPixmap, QImage, QPainter, QColor, QIcon, QTextCursor, QAction, 
                        QTextDocument, QTextCharFormat, QFont, QLinearGradient, QPen, 
                        QPainterPath)
from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput
from PyQt6.QtMultimediaWidgets import QVideoWidget
from docx import Document
import openpyxl
from pptx import Presentation

# 导入系统集成模块
try:
    from system_integration import SystemIntegration
except ImportError:
    SystemIntegration = None

# 导入自定义功能模块
try:
    from theme_system import ThemeSystem
    from layout_manager import LayoutManager
    from toolbar_manager import ToolbarManager
except ImportError as e:
    print(f"导入自定义模块失败: {e}")
    ThemeSystem = None
    LayoutManager = None
    ToolbarManager = None

# 过滤ebooklib的警告
warnings.filterwarnings('ignore', category=UserWarning, module='ebooklib.epub')
warnings.filterwarnings('ignore', category=FutureWarning, module='ebooklib.epub')

# 创建自定义的歌词编辑器类
class LyricTextEdit(QTextEdit):
    """自定义歌词编辑器，支持同步模式下的快捷键操作"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.main_window = parent
        self.sync_mode_enabled = False
        self.last_key_time = 0  # 用于防止按键过快导致的问题
    
    def set_main_window(self, main_window):
        """设置主窗口引用，用于调用主窗口方法"""
        self.main_window = main_window
    
    def set_sync_mode(self, enabled):
        """设置同步模式状态"""
        self.sync_mode_enabled = enabled
        self.last_key_time = 0  # 重置按键时间
    
    def keyPressEvent(self, event):
        """重写键盘事件处理，支持同步模式下的特殊按键操作"""
        # 只有在同步模式下才处理空格和回车键
        if self.sync_mode_enabled:
            # 添加按键防抖，避免快速连击导致的性能问题
            current_time = time.time() * 1000  # 转换为毫秒
            if current_time - self.last_key_time < 100:  # 100毫秒内的按键不处理
                return
            
            self.last_key_time = current_time
            
            # 处理空格键
            if event.key() == Qt.Key.Key_Space:
                if hasattr(self.main_window, 'insert_time_tag'):
                    # 使用QTimer延迟执行，避免UI阻塞
                    QTimer.singleShot(5, self.main_window.insert_time_tag)
                    return  # 不调用父类方法，防止插入空格
            
            # 处理回车键
            elif event.key() == Qt.Key.Key_Return or event.key() == Qt.Key.Key_Enter:
                # 首先将光标移动到行尾
                cursor = self.textCursor()
                cursor.movePosition(QTextCursor.MoveOperation.EndOfLine)
                self.setTextCursor(cursor)
                
                # 插入换行
                cursor.insertText("\n")
                
                # 在新行插入时间标签，使用QTimer延迟执行
                if hasattr(self.main_window, 'insert_time_tag'):
                    QTimer.singleShot(5, self.main_window.insert_time_tag)
                return  # 不调用父类方法，防止插入额外的换行
        
        # 其他情况下调用父类方法正常处理
        super().keyPressEvent(event)

# 添加桌面歌词窗口类，放在MainWindow类之前

class DesktopLyricWindow(QWidget):
    """桌面歌词窗口，显示在屏幕底部的透明窗口"""
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowFlags(
            Qt.WindowType.FramelessWindowHint |  # 无边框
            Qt.WindowType.WindowStaysOnTopHint |  # 置顶
            Qt.WindowType.Tool  # 设置为工具窗口，这样就不会在任务栏显示
        )
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)  # 透明背景
        self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)  # 无系统背景
        self.setAttribute(Qt.WidgetAttribute.WA_ShowWithoutActivating)  # 显示时不激活
        
        # 设置窗口样式
        self.setStyleSheet("""
            QWidget {
                background-color: rgba(0, 0, 0, 0);
                color: white;
            }
            QLabel {
                color: white;
                font-size: 16px;
            }
            QPushButton {
                background-color: rgba(0, 0, 0, 0.5);
                color: white;
                border: none;
                padding: 2px;
                border-radius: 2px;
            }
            QPushButton:hover {
                background-color: rgba(0, 0, 0, 0.7);
            }
        """)
        
        # 歌词设置
        self.current_text = ""
        self.next_text = ""
        self.font_size = 22
        self.opacity = 0.8
        self.background_color = QColor(0, 0, 0, 150)  # 半透明黑色背景
        self.text_color = QColor(255, 255, 255, 255)  # 白色文本
        self.highlight_color = QColor(25, 118, 210, 255)  # 高亮色
        
        # 布局
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(10, 10, 10, 10)
        
        # 歌词标签
        self.lyric_label = QLabel()
        self.lyric_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.lyric_label.setStyleSheet(f"""
            QLabel {{
                color: white;
                font-family: 'Microsoft YaHei', Arial;
                font-size: {self.font_size}px;
                font-weight: bold;
            }}
        """)
        self.layout.addWidget(self.lyric_label)
        
        # 下一句歌词标签
        self.next_lyric_label = QLabel()
        self.next_lyric_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.next_lyric_label.setStyleSheet(f"""
            QLabel {{
                color: rgba(255, 255, 255, 160);
                font-family: 'Microsoft YaHei', Arial;
                font-size: {self.font_size - 6}px;
            }}
        """)
        self.layout.addWidget(self.next_lyric_label)
        
        # 控制栏
        self.control_bar = QWidget()
        control_layout = QHBoxLayout(self.control_bar)
        control_layout.setContentsMargins(0, 0, 0, 0)
        
        # 关闭按钮
        self.close_btn = QPushButton("×")
        self.close_btn.setFixedSize(24, 24)
        self.close_btn.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
                font-size: 18px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
            }
        """)
        self.close_btn.clicked.connect(self.hide)
        
        # 锁定按钮
        self.lock_btn = QPushButton("🔒")
        self.lock_btn.setFixedSize(24, 24)
        self.lock_btn.setCheckable(True)
        self.lock_btn.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
            }
            QPushButton:checked {
                color: #1976D2;
            }
        """)
        self.lock_btn.clicked.connect(self.toggle_lock)
        
        # 字体大小按钮
        self.font_smaller_btn = QPushButton("A-")
        self.font_smaller_btn.setFixedSize(24, 24)
        self.font_smaller_btn.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
                font-size: 12px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
            }
        """)
        self.font_smaller_btn.clicked.connect(self.decrease_font_size)
        
        self.font_larger_btn = QPushButton("A+")
        self.font_larger_btn.setFixedSize(24, 24)
        self.font_larger_btn.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
                font-size: 12px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
            }
        """)
        self.font_larger_btn.clicked.connect(self.increase_font_size)
        
        # 透明度按钮
        self.opacity_down_btn = QPushButton("⬇")
        self.opacity_down_btn.setFixedSize(24, 24)
        self.opacity_down_btn.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
                font-size: 12px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
            }
        """)
        self.opacity_down_btn.clicked.connect(self.decrease_opacity)
        
        self.opacity_up_btn = QPushButton("⬆")
        self.opacity_up_btn.setFixedSize(24, 24)
        self.opacity_up_btn.setStyleSheet("""
            QPushButton {
                background-color: transparent;
                color: white;
                border: none;
                font-size: 12px;
            }
            QPushButton:hover {
                background-color: rgba(255, 255, 255, 50);
            }
        """)
        self.opacity_up_btn.clicked.connect(self.increase_opacity)
        
        # 添加按钮到控制栏
        control_layout.addWidget(self.lock_btn)
        control_layout.addWidget(self.font_smaller_btn)
        control_layout.addWidget(self.font_larger_btn)
        control_layout.addWidget(self.opacity_down_btn)
        control_layout.addWidget(self.opacity_up_btn)
        control_layout.addStretch()
        control_layout.addWidget(self.close_btn)
        
        self.layout.addWidget(self.control_bar)
        
        # 隐藏控制栏（鼠标悬停时显示）
        self.control_bar.setVisible(False)
        
        # 是否锁定，锁定后不可拖动
        self.is_locked = False
        
        # 拖动相关
        self.drag_position = None
        
        # 初始位置设置为屏幕底部中央
        self.set_default_position()
        
        # 设置默认宽度
        self.setMinimumWidth(600)
        self.resize(800, self.height())
    
    def set_default_position(self):
        """设置窗口默认位置（屏幕底部中央）"""
        desktop = QApplication.primaryScreen().geometry()
        width = min(800, desktop.width() - 100)  # 窗口宽度，确保不超过屏幕宽度
        height = 80  # 窗口高度
        
        x = (desktop.width() - width) // 2
        y = desktop.height() - height - 100  # 距离底部100像素
        
        self.setGeometry(x, y, width, height)
    
    def update_lyric(self, current_text, next_text=""):
        """更新当前显示的歌词和下一句歌词"""
        self.current_text = current_text
        self.next_text = next_text
        
        self.lyric_label.setText(current_text)
        self.next_lyric_label.setText(next_text)
        
        # 如果当前没有歌词，则显示提示
        if not current_text:
            self.lyric_label.setText("暂无歌词")
            self.next_lyric_label.setText("")
    
    def toggle_lock(self, checked):
        """切换锁定状态"""
        self.is_locked = checked
        if checked:
            self.lock_btn.setText("🔒")
        else:
            self.lock_btn.setText("🔓")
    
    def increase_font_size(self):
        """增加字体大小"""
        if self.font_size < 36:
            self.font_size += 2
            self.update_font_style()
    
    def decrease_font_size(self):
        """减小字体大小"""
        if self.font_size > 12:
            self.font_size -= 2
            self.update_font_style()
    
    def increase_opacity(self):
        """增加透明度"""
        if self.opacity < 1.0:
            self.opacity += 0.1
            self.opacity = min(1.0, self.opacity)
            self.update_font_style()
    
    def decrease_opacity(self):
        """减小透明度"""
        if self.opacity > 0.2:
            self.opacity -= 0.1
            self.opacity = max(0.2, self.opacity)
            self.update_font_style()
    
    def update_font_style(self):
        """更新字体样式"""
        self.lyric_label.setStyleSheet(f"""
            QLabel {{
                color: rgba(255, 255, 255, {int(255 * self.opacity)});
                font-family: 'Microsoft YaHei', Arial;
                font-size: {self.font_size}px;
                font-weight: bold;
            }}
        """)
        
        self.next_lyric_label.setStyleSheet(f"""
            QLabel {{
                color: rgba(255, 255, 255, {int(160 * self.opacity)});
                font-family: 'Microsoft YaHei', Arial;
                font-size: {self.font_size - 6}px;
            }}
        """)
        
        # 更新背景透明度
        self.update()
    
    def enterEvent(self, event):
        """鼠标进入窗口时显示控制栏"""
        self.control_bar.setVisible(True)
        # 对于PyQt6，不同的事件类型需要正确处理
        try:
            super().enterEvent(event)
        except TypeError:
            # PyQt6可能会根据Qt版本使用不同的参数
            pass
    
    def leaveEvent(self, event):
        """鼠标离开窗口时隐藏控制栏"""
        self.control_bar.setVisible(False)
        try:
            super().leaveEvent(event)
        except TypeError:
            pass
    
    def mousePressEvent(self, event):
        """鼠标按下事件，用于拖动窗口"""
        if not self.is_locked and event.button() == Qt.MouseButton.LeftButton:
            try:
                self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
            except AttributeError:
                # 兼容不同版本的PyQt，有些版本可能使用不同的方法名
                self.drag_position = event.globalPos() - self.frameGeometry().topLeft()
        try:
            super().mousePressEvent(event)
        except TypeError:
            pass
    
    def mouseMoveEvent(self, event):
        """鼠标移动事件，用于拖动窗口"""
        if not self.is_locked and self.drag_position:
            try:
                self.move(event.globalPosition().toPoint() - self.drag_position)
            except AttributeError:
                # 兼容不同版本的PyQt
                self.move(event.globalPos() - self.drag_position)
        try:
            super().mouseMoveEvent(event)
        except TypeError:
            pass
    
    def mouseReleaseEvent(self, event):
        """鼠标释放事件，结束拖动"""
        self.drag_position = None
        try:
            super().mouseReleaseEvent(event)
        except TypeError:
            pass
    
    def paintEvent(self, event):
        """绘制事件，用于绘制半透明背景"""
        painter = QPainter(self)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        
        # 设置背景颜色（使用设置的不透明度）
        background_color = QColor(
            0, 0, 0, 
            int(150 * self.opacity)  # 背景透明度
        )
        
        # 创建圆角矩形路径
        path = QPainterPath()
        # 将QRect转换为QRectF
        rect = QRectF(self.rect())
        path.addRoundedRect(rect, 10.0, 10.0)
        
        # 填充背景
        painter.fillPath(path, background_color)

class MainWindow(QMainWindow):
    def __init__(self, file_path=None):
        """初始化主窗口"""
        super().__init__()
        
        # 媒体播放器
        self.media_player = QMediaPlayer()
        self.video_widget = QVideoWidget()
        self.media_player.setVideoOutput(self.video_widget)
        
        # 当前文件信息
        self.current_file = None
        self.current_encoding = "UTF-8"
        self.text_modified = False
        self.current_zoom = 100
        self.is_fullscreen = False
        self.control_panel_visible = True
        
        # PDF文档相关
        self.pdf_doc = None
        self.current_page = 0
        self.page_images = []
        self.thumbnails_visible = False
        self.pdf_scale_factor = 1.0
        
        # 电子书相关
        self.ebook_doc = None
        self.chapters = []
        self.chapter_titles = []
        self.current_chapter = 0
        self.ebook_font_size = 16
        
        # 音乐播放列表相关
        self.playlist = []  # 存储播放列表中的文件路径
        self.current_playlist_index = -1  # 当前播放的索引
        self.play_mode = "sequence"  # 播放模式：sequence（顺序）, loop（循环）, random（随机）
        
        # 歌词相关
        self.lyrics_dict = {}  # 存储歌词，键为音乐文件路径，值为歌词文本
        self.current_lyrics = ""  # 当前显示的歌词
        self.lyrics_file_path = os.path.join(os.path.expanduser("~"), ".gofile", "lyrics.json")
        self.timed_lyrics = {}  # 带时间标签的歌词，键为时间（毫秒），值为歌词文本
        self.current_lyric_index = -1  # 当前高亮显示的歌词索引
        self.center_lyrics_font_size = 16  # 中央歌词字体大小（初始值）
        self.center_lyrics_font_size_min = 12  # 最小字体大小
        self.center_lyrics_font_size_max = 36  # 最大字体大小
        
        # 桌面歌词窗口
        self.desktop_lyric_window = DesktopLyricWindow()  # 不传入parent参数
        self.desktop_lyric_enabled = False  # 桌面歌词是否启用
        
        # 最近文件列表
        self.max_recent_files = 100
        self.recent_files = []
        self.recent_files_file_path = os.path.join(os.path.expanduser("~"), ".gofile", "recent_files.json")
        
        # 文件状态
        self.file_states = {}
        
        # 搜索相关
        self.last_search = ""
        self.case_sensitive = False
        self.search_wrap = True
        self.search_backward = False
        self.find_dialog = None
        self.replace_dialog = None
        
        # 设置应用标题和图标
        self.setWindowTitle("GoFile")
        self.setGeometry(100, 100, 1000, 800)
        
        # 设置应用图标
        app_icon = QIcon()
        app_icon.addPixmap(self.create_app_icon())
        self.setWindowIcon(app_icon)
        QApplication.setWindowIcon(app_icon)
        
        # 创建右键菜单
        self.context_menu = QMenu(self)
        self.setup_context_menu()
        
        # 启用拖放支持
        self.setAcceptDrops(True)
        
        # 加载最近文件、状态和歌词
        self.load_recent_files()
        self.load_lyrics()
        
        # 创建菜单栏 - 先创建菜单栏，但不连接编辑功能信号
        self.create_menus_without_connections()
        
        # 创建状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage("就绪")
        
        # 添加状态栏永久显示项
        self.cursor_position_label = QLabel("行: 1, 列: 1")
        self.statusBar.addPermanentWidget(self.cursor_position_label)
        
        self.selection_label = QLabel("选中: 0 字符")
        self.statusBar.addPermanentWidget(self.selection_label)
        
        self.encoding_label = QLabel("编码: UTF-8")
        self.statusBar.addPermanentWidget(self.encoding_label)
        
        self.file_info_label = QLabel("总行数: 0 | 大小: 0 KB")
        self.statusBar.addPermanentWidget(self.file_info_label)
        
        # 添加文件类型标签
        self.file_type_label = QLabel("文件类型: 未知")
        self.statusBar.addPermanentWidget(self.file_type_label)
        
        # 创建中央窗口部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        self.main_layout = QVBoxLayout()
        self.main_layout.setContentsMargins(0, 0, 0, 0)  # 移除边距
        self.main_layout.setSpacing(0)  # 移除间距
        central_widget.setLayout(self.main_layout)
        
        # 创建水平分割器，用于缩略图和主视图
        self.splitter = QSplitter(Qt.Orientation.Horizontal)
        self.main_layout.addWidget(self.splitter)
        
        # 创建缩略图面板
        self.thumbnails_widget = QWidget()
        self.thumbnails_layout = QVBoxLayout()
        self.thumbnails_layout.setContentsMargins(5, 5, 5, 5)
        self.thumbnails_widget.setLayout(self.thumbnails_layout)
        
        # 缩略图标签
        self.thumb_label = QLabel("缩略图")
        self.thumbnails_layout.addWidget(self.thumb_label)
        
        # 缩略图列表
        self.thumbnail_list = QListWidget()
        self.thumbnail_list.setIconSize(QSize(100, 140))
        self.thumbnail_list.itemClicked.connect(self.thumbnail_clicked)
        self.thumbnails_layout.addWidget(self.thumbnail_list)
        
        # 初始隐藏缩略图面板
        self.thumbnails_widget.setVisible(False)
        self.splitter.addWidget(self.thumbnails_widget)
        
        # 创建预览容器
        preview_container = QWidget()
        preview_layout = QVBoxLayout()
        preview_layout.setContentsMargins(0, 0, 0, 0)
        preview_layout.setSpacing(0)
        preview_container.setLayout(preview_layout)
        
        # 创建预览区域
        self.preview_area = QScrollArea()
        self.preview_area.setWidgetResizable(True)
        self.preview_widget = QWidget()
        # 设置预览区域的背景色为白色
        self.preview_widget.setStyleSheet("background-color: white;")
        self.preview_layout = QVBoxLayout()
        self.preview_layout.setContentsMargins(0, 0, 0, 0)  # 移除边距
        self.preview_layout.setSpacing(0)  # 移除间距
        self.preview_widget.setLayout(self.preview_layout)
        self.preview_area.setWidget(self.preview_widget)
        preview_layout.addWidget(self.preview_area)
        
        # 创建控制器区域
        self.control_panel = QWidget()
        self.control_layout = QHBoxLayout()  # 保存为实例变量
        self.control_layout.setContentsMargins(10, 5, 10, 5)
        
        # 缩放比例标签
        self.zoom_label = QLabel("100%")
        self.zoom_label.setFixedWidth(50)
        self.zoom_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.control_layout.addWidget(self.zoom_label)
        
        # 减号按钮
        self.zoom_out_btn = QPushButton("-")
        self.zoom_out_btn.setFixedSize(24, 24)
        self.zoom_out_btn.clicked.connect(self.zoom_out)
        self.control_layout.addWidget(self.zoom_out_btn)
        
        # 缩放滑动条
        self.zoom_slider = QSlider(Qt.Orientation.Horizontal)
        self.zoom_slider.setMinimum(10)  # 10% 最小缩放
        self.zoom_slider.setMaximum(500)  # 500% 最大缩放
        self.zoom_slider.setValue(100)  # 默认100%
        self.zoom_slider.valueChanged.connect(self.on_zoom_changed)
        self.zoom_slider.setFixedWidth(100)  # 设置滑动条固定宽度
        self.control_layout.addWidget(self.zoom_slider)
        
        # 加号按钮
        self.zoom_in_btn = QPushButton("+")
        self.zoom_in_btn.setFixedSize(24, 24)
        self.zoom_in_btn.clicked.connect(self.zoom_in)
        self.control_layout.addWidget(self.zoom_in_btn)
        
        # 页码选择器（仅在PDF模式下显示）
        self.page_label = QLabel("页码:")
        self.page_label.setVisible(False)
        self.control_layout.addWidget(self.page_label)
        
        self.page_combo = QComboBox()
        self.page_combo.setFixedWidth(80)
        self.page_combo.currentIndexChanged.connect(self.page_changed)
        self.page_combo.setVisible(False)
        self.control_layout.addWidget(self.page_combo)
        
        # 缩略图切换按钮
        self.thumbnail_btn = QPushButton("缩略图")
        self.thumbnail_btn.setCheckable(True)
        self.thumbnail_btn.setVisible(False)
        self.thumbnail_btn.clicked.connect(self.toggle_thumbnails)
        self.control_layout.addWidget(self.thumbnail_btn)
        
        # 编辑模式切换按钮
        self.edit_btn = QPushButton("编辑模式")
        self.edit_btn.setCheckable(True)
        self.edit_btn.setVisible(False)
        self.edit_btn.clicked.connect(self.toggle_edit_mode)
        self.control_layout.addWidget(self.edit_btn)
        
        # 保存按钮
        self.save_btn = QPushButton("保存")
        self.save_btn.setVisible(False)
        self.save_btn.clicked.connect(self.save_file)
        self.control_layout.addWidget(self.save_btn)
        
        # 创建视频播放器组件
        self.video_widget = QVideoWidget()
        self.video_widget.setVisible(False)
        self.preview_layout.addWidget(self.video_widget)
        
        # 创建媒体播放器
        self.media_player = QMediaPlayer()
        self.audio_output = QAudioOutput()
        self.media_player.setAudioOutput(self.audio_output)
        self.media_player.setVideoOutput(self.video_widget)
        
        # 视频控制按钮
        self.play_btn = QPushButton("播放")
        self.play_btn.setVisible(False)
        self.play_btn.clicked.connect(self.toggle_play)
        self.control_layout.addWidget(self.play_btn)
        
        # 视频进度条
        self.video_slider = QSlider(Qt.Orientation.Horizontal)
        self.video_slider.setVisible(False)
        self.video_slider.sliderMoved.connect(self.set_video_position)
        self.control_layout.addWidget(self.video_slider)
        
        # 视频相关变量
        self.is_playing = False
        
        # 添加弹性空间
        self.control_layout.addStretch()
        
        # 添加阅读进度标签
        self.progress_label = QLabel()
        self.progress_label.setVisible(False)
        self.control_layout.addWidget(self.progress_label)
        
        self.control_panel.setLayout(self.control_layout)
        preview_layout.addWidget(self.control_panel)
        
        self.splitter.addWidget(preview_container)
        
        # 初始设置分割比例
        self.splitter.setSizes([200, 800])
        
        # 连接滚动条信号
        self.preview_area.verticalScrollBar().valueChanged.connect(self.handle_scroll)
        
        # 创建Markdown分屏容器
        self.markdown_splitter = QSplitter(Qt.Orientation.Horizontal)
        self.markdown_splitter.setVisible(False)
        self.preview_layout.addWidget(self.markdown_splitter)
        
        # 创建文本编辑器（用于显示文本文件）
        self.text_editor = QTextEdit()
        self.text_editor.setReadOnly(True)
        self.preview_layout.addWidget(self.text_editor)
        
        # 创建Markdown编辑器和预览器
        self.markdown_editor = QTextEdit()
        self.markdown_editor.setPlaceholderText("在此输入Markdown内容...")
        self.markdown_editor.textChanged.connect(self.on_markdown_text_changed)
        
        self.markdown_preview = QTextEdit()
        self.markdown_preview.setReadOnly(True)
        
        # 将编辑器和预览器添加到分割器
        self.markdown_splitter.addWidget(self.markdown_editor)
        self.markdown_splitter.addWidget(self.markdown_preview)
        self.markdown_splitter.setSizes([500, 500])  # 设置初始比例为1:1
        
        # 创建图片标签（用于显示图片）
        self.image_label = QLabel()
        self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        # 启用鼠标追踪
        self.image_label.setMouseTracking(True)
        # 设置焦点策略，使其可以接收键盘事件
        self.image_label.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
        # 设置大小策略，使其能够占满可用空间
        from PyQt6.QtWidgets import QSizePolicy
        self.image_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        self.preview_layout.addWidget(self.image_label)
        
        # 文档相关变量
        self.current_file = None
        self.pdf_doc = None
        self.current_page = 0
        self.current_image = None  # 保存原始图片
        self.zoom_factor = 1.0
        self.is_editing = False  # 是否处于编辑模式
        self.text_changed = False  # 文本是否被修改
        self.markdown_preview_mode = False  # 是否处于Markdown分屏预览模式
        
        # 缩放相关变量
        self.min_zoom = 0.1
        self.max_zoom = 5.0
        self.zoom_step = 1.2
        
        # 拖拽相关变量
        self.is_dragging = False
        self.drag_start_pos = None
        self.scroll_start_pos = None
        
        # 页面切换相关变量
        self.is_page_turning = False  # 防止页面切换时触发滚动事件
        
        # 添加电子书相关变量
        self.ebook_doc = None
        self.current_chapter = 0
        self.chapters = []
        self.chapter_titles = []
        
        # 添加字体设置
        self.font_size = 16
        self.line_height = 1.5
        self.font_family = "Microsoft YaHei"
        
        # 添加阅读模式按钮
        self.read_mode_btn = QPushButton("阅读模式")
        self.read_mode_btn.setCheckable(True)
        self.read_mode_btn.setVisible(False)
        self.read_mode_btn.clicked.connect(self.toggle_read_mode)
        self.control_layout.addWidget(self.read_mode_btn)
        
        # 添加字体大小控制
        self.font_size_label = QLabel("字体大小")
        self.font_size_label.setVisible(False)
        self.control_layout.addWidget(self.font_size_label)
        
        self.font_size_slider = QSlider(Qt.Orientation.Horizontal)
        self.font_size_slider.setMinimum(12)
        self.font_size_slider.setMaximum(24)
        self.font_size_slider.setValue(16)
        self.font_size_slider.setVisible(False)
        self.font_size_slider.valueChanged.connect(self.on_font_size_changed)
        self.control_layout.addWidget(self.font_size_slider)
        
        # 添加章节选择器
        self.chapter_combo = QComboBox()
        self.chapter_combo.setVisible(False)
        self.chapter_combo.currentIndexChanged.connect(self.chapter_changed)
        self.control_layout.addWidget(self.chapter_combo)
        
        # 现在连接编辑功能信号
        self.connect_menu_actions()
        
        # 加载保存的播放列表
        self.load_playlist()
        
        # 加载歌词数据
        self.load_lyrics()
        
        # 初始化系统集成功能
        self.system_integration = None
        if SystemIntegration:
            try:
                self.system_integration = SystemIntegration(self)
                # 设置系统托盘
                if self.system_integration.setup_system_tray():
                    self.statusBar.showMessage("系统托盘已启用")
            except Exception as e:
                print(f"系统集成功能初始化失败: {e}")
        
        # 初始化主题系统
        self.theme_system = None
        if ThemeSystem:
            try:
                self.theme_system = ThemeSystem(self)
                # 加载保存的主题设置
                self.theme_system.load_config()
                # 应用默认主题
                self.theme_system.apply_theme(self.theme_system.current_theme)
            except Exception as e:
                print(f"主题系统初始化失败: {e}")
        
        # 初始化布局管理器
        self.layout_manager = None
        if LayoutManager:
            try:
                self.layout_manager = LayoutManager(self)
                # 加载保存的布局配置
                self.layout_manager.load_layout()
            except Exception as e:
                print(f"布局管理器初始化失败: {e}")
        
        # 初始化工具栏管理器
        self.toolbar_manager = None
        if ToolbarManager:
            try:
                self.toolbar_manager = ToolbarManager(self)
                # 创建默认工具栏
                self.toolbar_manager.create_default_toolbar()
                # 加载保存的工具栏配置
                self.toolbar_manager.load_config()
            except Exception as e:
                print(f"工具栏管理器初始化失败: {e}")
        
        if file_path:
            self.current_file = file_path
            self.load_file(file_path)
        else:
            # 如果没有指定文件路径，设置初始界面
            self.text_editor.setVisible(True)
            self.image_label.setVisible(False)
            self.statusBar.showMessage("就绪")

    def create_menus_without_connections(self):
        """创建菜单栏但不连接编辑功能信号"""
        # 创建菜单栏
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu("文件(&F)")
        
        # 新建文件
        new_file_action = QAction("新建文件(&N)", self)
        new_file_action.setShortcut("Ctrl+N")
        new_file_action.triggered.connect(self.new_file)
        file_menu.addAction(new_file_action)
        
        # 打开
        open_action = QAction("打开(&O)...", self)
        open_action.setShortcut("Ctrl+O")
        open_action.triggered.connect(self.open_file)
        file_menu.addAction(open_action)
        
        # 打开文件夹
        open_folder_action = QAction("打开文件夹(&D)...", self)
        open_folder_action.setShortcut("Ctrl+Shift+O")
        open_folder_action.triggered.connect(self.open_folder)
        file_menu.addAction(open_folder_action)
        
        file_menu.addSeparator()
        
        # 保存
        self.save_action = QAction("保存(&S)", self)
        self.save_action.setShortcut("Ctrl+S")
        self.save_action.triggered.connect(self.save_file)
        self.save_action.setEnabled(False)  # 默认禁用保存按钮
        file_menu.addAction(self.save_action)
        
        # 另存为
        save_as_action = QAction("另存为(&A)...", self)
        save_as_action.setShortcut("Ctrl+Shift+S")
        save_as_action.triggered.connect(self.save_file_as)
        file_menu.addAction(save_as_action)
        
        file_menu.addSeparator()
        
        # 最近的文件
        self.recent_files_menu = QMenu("最近的文件(&R)", self)
        file_menu.addMenu(self.recent_files_menu)
        self.update_recent_files_menu()
        
        file_menu.addSeparator()
        
        # 退出
        exit_action = QAction("退出(&X)", self)
        exit_action.setShortcut("Alt+F4")
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        
        # 编辑菜单
        edit_menu = menubar.addMenu("编辑(&E)")
        
        # 添加编辑功能（但不连接）
        # 撤销
        self.undo_action = QAction("撤销(&U)", self)
        self.undo_action.setShortcut("Ctrl+Z")
        self.undo_action.setEnabled(False)  # 默认禁用
        edit_menu.addAction(self.undo_action)
        
        # 重做
        self.redo_action = QAction("重做(&R)", self)
        self.redo_action.setShortcut("Ctrl+Y")
        self.redo_action.setEnabled(False)  # 默认禁用
        edit_menu.addAction(self.redo_action)
        
        edit_menu.addSeparator()
        
        # 剪切
        self.cut_action = QAction("剪切(&T)", self)
        self.cut_action.setShortcut("Ctrl+X")
        self.cut_action.setEnabled(False)  # 默认禁用
        edit_menu.addAction(self.cut_action)
        
        # 复制
        self.copy_action = QAction("复制(&C)", self)
        self.copy_action.setShortcut("Ctrl+C")
        self.copy_action.setEnabled(True)  # 复制功能始终可用
        edit_menu.addAction(self.copy_action)
        
        # 粘贴
        self.paste_action = QAction("粘贴(&P)", self)
        self.paste_action.setShortcut("Ctrl+V")
        self.paste_action.setEnabled(False)  # 默认禁用
        edit_menu.addAction(self.paste_action)
        
        edit_menu.addSeparator()
        
        # 删除
        self.delete_action = QAction("删除(&D)", self)
        self.delete_action.setShortcut("Delete")
        self.delete_action.setEnabled(False)  # 默认禁用
        edit_menu.addAction(self.delete_action)
        
        # 全选
        self.select_all_action = QAction("全选(&A)", self)
        self.select_all_action.setShortcut("Ctrl+A")
        self.select_all_action.setEnabled(True)  # 全选功能始终可用
        edit_menu.addAction(self.select_all_action)
        
        edit_menu.addSeparator()
        
        # 查找
        self.find_action = QAction("查找(&F)...", self)
        self.find_action.setShortcut("Ctrl+F")
        self.find_action.setEnabled(True)  # 查找功能始终可用
        edit_menu.addAction(self.find_action)
        
        # 替换
        self.replace_action = QAction("替换(&H)...", self)
        self.replace_action.setShortcut("Ctrl+H")
        self.replace_action.setEnabled(False)  # 默认禁用
        edit_menu.addAction(self.replace_action)
        
        # 视图菜单
        view_menu = menubar.addMenu("视图(&V)")
        
        # 缩放子菜单
        zoom_menu = QMenu("缩放(&Z)", self)
        view_menu.addMenu(zoom_menu)
        
        # 放大
        zoom_in_action = QAction("放大(&I)", self)
        zoom_in_action.setShortcut("Ctrl+=")
        zoom_in_action.triggered.connect(self.zoom_in)
        zoom_menu.addAction(zoom_in_action)
        
        # 缩小
        zoom_out_action = QAction("缩小(&O)", self)
        zoom_out_action.setShortcut("Ctrl+-")
        zoom_out_action.triggered.connect(self.zoom_out)
        zoom_menu.addAction(zoom_out_action)
        
        # 重置缩放
        zoom_reset_action = QAction("重置缩放(&R)", self)
        zoom_reset_action.setShortcut("Ctrl+0")
        zoom_reset_action.triggered.connect(self.zoom_reset)
        zoom_menu.addAction(zoom_reset_action)
        
        # 适应窗口
        fit_window_action = QAction("适应窗口(&F)", self)
        fit_window_action.setShortcut("Ctrl+9")
        fit_window_action.triggered.connect(self.fit_to_window)
        zoom_menu.addAction(fit_window_action)
        
        view_menu.addSeparator()
        
        # 添加全屏切换动作
        self.toggle_fullscreen_action = QAction("全屏模式(&F)", self)
        self.toggle_fullscreen_action.setShortcut("F11")
        self.toggle_fullscreen_action.triggered.connect(self.toggle_fullscreen)
        view_menu.addAction(self.toggle_fullscreen_action)
        
        view_menu.addSeparator()
        
        # 添加状态栏显示/隐藏动作
        self.toggle_statusbar_action = QAction("状态栏(&S)", self)
        self.toggle_statusbar_action.setCheckable(True)
        self.toggle_statusbar_action.setChecked(True)  # 默认显示状态栏
        self.toggle_statusbar_action.triggered.connect(self.toggle_statusbar)
        view_menu.addAction(self.toggle_statusbar_action)
        
        # 添加功能栏显示/隐藏动作
        self.toggle_control_panel_action = QAction("工具栏(&T)", self)
        self.toggle_control_panel_action.setCheckable(True)
        self.toggle_control_panel_action.setChecked(True)  # 默认显示功能栏
        self.toggle_control_panel_action.triggered.connect(self.toggle_control_panel)
        view_menu.addAction(self.toggle_control_panel_action)
        
        view_menu.addSeparator()
        
        # 添加Markdown分屏预览切换动作
        self.toggle_markdown_preview_action = QAction("Markdown分屏预览(&M)", self)
        self.toggle_markdown_preview_action.setCheckable(True)
        self.toggle_markdown_preview_action.setChecked(False)
        self.toggle_markdown_preview_action.triggered.connect(self.toggle_markdown_preview_mode)
        view_menu.addAction(self.toggle_markdown_preview_action)
        
        # 媒体菜单（音频/视频相关功能）
        media_menu = menubar.addMenu("媒体(&M)")
        
        # 播放控制子菜单
        playback_menu = QMenu("播放控制(&P)", self)
        media_menu.addMenu(playback_menu)
        
        # 播放/暂停
        self.play_pause_action = QAction("播放/暂停(&P)", self)
        self.play_pause_action.setShortcut("Space")
        self.play_pause_action.triggered.connect(self.toggle_play_pause)
        playback_menu.addAction(self.play_pause_action)
        
        # 停止
        self.stop_action = QAction("停止(&S)", self)
        self.stop_action.setShortcut("Ctrl+.")
        self.stop_action.triggered.connect(self.stop_media)
        playback_menu.addAction(self.stop_action)
        
        playback_menu.addSeparator()
        
        # 上一个
        self.previous_action = QAction("上一个(&B)", self)
        self.previous_action.setShortcut("Ctrl+Left")
        self.previous_action.triggered.connect(self.previous_media)
        playback_menu.addAction(self.previous_action)
        
        # 下一个
        self.next_action = QAction("下一个(&N)", self)
        self.next_action.setShortcut("Ctrl+Right")
        self.next_action.triggered.connect(self.next_media)
        playback_menu.addAction(self.next_action)
        
        # 音量控制子菜单
        volume_menu = QMenu("音量(&V)", self)
        media_menu.addMenu(volume_menu)
        
        # 音量增加
        volume_up_action = QAction("音量增加(&U)", self)
        volume_up_action.setShortcut("Ctrl+Up")
        volume_up_action.triggered.connect(self.volume_up)
        volume_menu.addAction(volume_up_action)
        
        # 音量减少
        volume_down_action = QAction("音量减少(&D)", self)
        volume_down_action.setShortcut("Ctrl+Down")
        volume_down_action.triggered.connect(self.volume_down)
        volume_menu.addAction(volume_down_action)
        
        # 静音
        mute_action = QAction("静音(&M)", self)
        mute_action.setShortcut("M")
        mute_action.triggered.connect(self.toggle_mute)
        volume_menu.addAction(mute_action)
        
        media_menu.addSeparator()
        
        # 桌面歌词
        self.desktop_lyric_action = QAction("桌面歌词(&L)", self)
        self.desktop_lyric_action.setCheckable(True)
        self.desktop_lyric_action.setChecked(False)
        self.desktop_lyric_action.triggered.connect(self.toggle_desktop_lyric)
        media_menu.addAction(self.desktop_lyric_action)
        
        # 工具菜单
        tools_menu = menubar.addMenu("工具(&T)")
        
        # 文件信息
        file_info_action = QAction("文件信息(&I)...", self)
        file_info_action.setShortcut("Alt+Enter")
        file_info_action.triggered.connect(self.show_file_info)
        tools_menu.addAction(file_info_action)
        
        tools_menu.addSeparator()
        
        # 编码转换
        encoding_menu = QMenu("编码转换(&E)", self)
        tools_menu.addMenu(encoding_menu)
        
        # 常用编码选项
        encodings = ["UTF-8", "GBK", "GB2312", "Big5", "ASCII", "ISO-8859-1"]
        for encoding in encodings:
            action = QAction(encoding, self)
            action.triggered.connect(lambda checked, enc=encoding: self.convert_encoding(enc))
            encoding_menu.addAction(action)
        
        tools_menu.addSeparator()
        
        # 系统集成子菜单
        if SystemIntegration:
            integration_menu = QMenu("系统集成(&I)", self)
            tools_menu.addMenu(integration_menu)
            
            # 安装右键菜单
            install_context_menu_action = QAction("安装右键菜单(&C)", self)
            install_context_menu_action.triggered.connect(self.install_context_menu)
            integration_menu.addAction(install_context_menu_action)
            
            # 卸载右键菜单
            uninstall_context_menu_action = QAction("卸载右键菜单(&U)", self)
            uninstall_context_menu_action.triggered.connect(self.uninstall_context_menu)
            integration_menu.addAction(uninstall_context_menu_action)
            
            integration_menu.addSeparator()
            
            # 设置文件关联
            set_file_associations_action = QAction("设置文件关联(&A)", self)
            set_file_associations_action.triggered.connect(self.set_file_associations)
            integration_menu.addAction(set_file_associations_action)
            
            # 移除文件关联
            remove_file_associations_action = QAction("移除文件关联(&R)", self)
            remove_file_associations_action.triggered.connect(self.remove_file_associations)
            integration_menu.addAction(remove_file_associations_action)
            
            tools_menu.addSeparator()
        
        # 主题设置
        if ThemeSystem:
            theme_action = QAction("主题设置(&T)...", self)
            theme_action.triggered.connect(self.show_theme_settings)
            tools_menu.addAction(theme_action)
        
        # 布局设置
        if LayoutManager:
            layout_action = QAction("布局设置(&L)...", self)
            layout_action.triggered.connect(self.show_layout_settings)
            tools_menu.addAction(layout_action)
        
        # 工具栏设置
        if ToolbarManager:
            toolbar_action = QAction("工具栏设置(&B)...", self)
            toolbar_action.triggered.connect(self.show_toolbar_settings)
            tools_menu.addAction(toolbar_action)
        
        tools_menu.addSeparator()
        
        # 设置
        settings_action = QAction("设置(&S)...", self)
        settings_action.triggered.connect(self.show_settings)
        tools_menu.addAction(settings_action)
        
        # 窗口菜单
        window_menu = menubar.addMenu("窗口(&W)")
        
        # 添加新建窗口选项
        self.new_window_action = QAction("新建窗口(&N)", self)
        self.new_window_action.setShortcut("Ctrl+Shift+N")
        self.new_window_action.triggered.connect(self.create_new_window)
        window_menu.addAction(self.new_window_action)
        
        window_menu.addSeparator()
        
        # 最小化
        minimize_action = QAction("最小化(&M)", self)
        minimize_action.setShortcut("Ctrl+M")
        minimize_action.triggered.connect(self.showMinimized)
        window_menu.addAction(minimize_action)
        
        # 最大化/还原
        self.maximize_action = QAction("最大化(&X)", self)
        self.maximize_action.triggered.connect(self.toggle_maximize)
        window_menu.addAction(self.maximize_action)
        
        window_menu.addSeparator()
        
        # 添加刷新窗口列表选项
        self.refresh_windows_action = QAction("刷新窗口列表(&R)", self)
        self.refresh_windows_action.triggered.connect(self.refresh_window_menu)
        window_menu.addAction(self.refresh_windows_action)
        
        # 添加窗口分隔符和窗口列表
        window_menu.addSeparator()
        self.window_menu = window_menu
        
        # 初始化全局窗口列表（如果不存在）
        global all_windows
        if not hasattr(sys.modules[__name__], 'all_windows'):
            all_windows = []
        
        # 如果当前窗口不在列表中，添加它
        if self not in all_windows:
            all_windows.append(self)
        
        # 刷新窗口菜单
        self.refresh_window_menu()
        
        # 帮助菜单
        help_menu = menubar.addMenu("帮助(&H)")
        
        # 使用说明
        help_action = QAction("使用说明(&H)...", self)
        help_action.setShortcut("F1")
        help_action.triggered.connect(self.show_help)
        help_menu.addAction(help_action)
        
        # 快捷键
        shortcuts_action = QAction("快捷键(&K)...", self)
        shortcuts_action.triggered.connect(self.show_shortcuts)
        help_menu.addAction(shortcuts_action)
        
        help_menu.addSeparator()
        
        # 检查更新
        update_action = QAction("检查更新(&U)...", self)
        update_action.triggered.connect(self.check_updates)
        help_menu.addAction(update_action)
        
        help_menu.addSeparator()
        
        # 关于
        about_action = QAction("关于 GoFile(&A)...", self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)

    def connect_menu_actions(self):
        """连接编辑菜单动作"""
        # 现在text_editor已创建，可以连接信号
        self.undo_action.triggered.connect(self.text_editor.undo)
        self.redo_action.triggered.connect(self.text_editor.redo)
        self.cut_action.triggered.connect(self.text_editor.cut)
        self.copy_action.triggered.connect(self.text_editor.copy)
        self.paste_action.triggered.connect(self.text_editor.paste)
        self.delete_action.triggered.connect(lambda: self.text_editor.textCursor().deleteChar())
        self.select_all_action.triggered.connect(self.text_editor.selectAll)
        self.find_action.triggered.connect(self.show_find_dialog)
        self.replace_action.triggered.connect(self.show_replace_dialog)
        
        # 连接光标位置变化信号
        self.text_editor.cursorPositionChanged.connect(self.update_cursor_position)
        # 连接选择变化信号
        self.text_editor.selectionChanged.connect(self.update_selection_info)
    
    def update_cursor_position(self):
        """更新状态栏中的光标位置信息"""
        if not self.text_editor.isVisible():
            return
            
        cursor = self.text_editor.textCursor()
        line = cursor.blockNumber() + 1
        column = cursor.columnNumber() + 1
        self.cursor_position_label.setText(f"行: {line}, 列: {column}")
        
    def update_selection_info(self):
        """更新状态栏中的选择信息"""
        if not self.text_editor.isVisible():
            return
            
        cursor = self.text_editor.textCursor()
        if cursor.hasSelection():
            selected_text = cursor.selectedText()
            length = len(selected_text)
            self.selection_label.setText(f"选中: {length} 字符")
        else:
            self.selection_label.setText("选中: 0 字符")
    
    def update_text_file_info(self, file_path, encoding="UTF-8"):
        """更新文本文件信息"""
        if not self.text_editor.isVisible():
            return
            
        # 获取文件大小
        try:
            file_size = os.path.getsize(file_path)
            if file_size < 1024:
                size_str = f"{file_size} B"
            elif file_size < 1024 * 1024:
                size_str = f"{file_size / 1024:.1f} KB"
            else:
                size_str = f"{file_size / (1024 * 1024):.1f} MB"
            
            # 计算总行数
            total_lines = self.text_editor.document().blockCount()
            
            # 更新状态栏信息
            self.encoding_label.setText(f"编码: {encoding}")
            self.file_info_label.setText(f"总行数: {total_lines} | 大小: {size_str}")
        except Exception as e:
            print(f"更新文件信息失败: {str(e)}")
            self.file_info_label.setText("文件信息获取失败")
    
    def update_statusbar_for_file_type(self):
        """根据当前文件类型更新状态栏"""
        is_text_file = self.text_editor.isVisible()
        
        # 显示或隐藏文本相关状态栏项
        self.cursor_position_label.setVisible(is_text_file)
        self.selection_label.setVisible(is_text_file)
        self.encoding_label.setVisible(is_text_file)
        self.file_info_label.setVisible(is_text_file)
        
        # 如果不是文本文件，清除这些信息
        if not is_text_file:
            self.cursor_position_label.setText("行: 1, 列: 1")
            self.selection_label.setText("选中: 0 字符")
            self.encoding_label.setText("编码: UTF-8")
            self.file_info_label.setText("总行数: 0 | 大小: 0 KB")
        
        # 确定当前文件类型
        is_image_file = self.image_label.isVisible() and not self.video_widget.isVisible() and (not hasattr(self, 'audio_time_label') or (hasattr(self, 'audio_time_label') and not self.audio_time_label.isVisible()))
        is_pdf_file = hasattr(self, 'pdf_doc') and self.pdf_doc
        is_video_file = self.video_widget.isVisible()
        is_audio_file = hasattr(self, 'audio_time_label') and self.audio_time_label.isVisible()
        is_ebook_file = hasattr(self, 'ebook_doc') and self.ebook_doc
        
        # 更新文件类型标签
        if not hasattr(self, 'current_file') or not self.current_file:
            self.file_type_label.setText("文件类型: 未知")
            return
            
        file_ext = os.path.splitext(self.current_file)[1].lower()
        
        if is_text_file:
            if file_ext in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']:
                self.file_type_label.setText("Markdown文档")
            elif self.is_code_file(self.current_file):
                try:
                    lexer = get_lexer_for_filename(self.current_file)
                    self.file_type_label.setText(f"{lexer.name}代码")
                except:
                    self.file_type_label.setText("代码文件")
            else:
                self.file_type_label.setText("文本文件")
        elif is_image_file:
            self.file_type_label.setText("图片文件")
        elif is_pdf_file:
            self.file_type_label.setText("PDF文档")
        elif is_video_file:
            self.file_type_label.setText("视频文件")
        elif is_audio_file:
            self.file_type_label.setText(f"音乐文件 | {file_ext[1:].upper()}")
        elif is_ebook_file:
            self.file_type_label.setText("电子书")
        elif file_ext in ['.docx', '.doc']:
            self.file_type_label.setText("Word文档")
        elif file_ext in ['.xlsx', '.xls']:
            self.file_type_label.setText("Excel表格")
        elif file_ext in ['.pptx', '.ppt']:
            self.file_type_label.setText("PowerPoint演示文稿")
        elif file_ext in ['.odt', '.ods', '.odp']:
            self.file_type_label.setText("OpenDocument文档")
        else:
            self.file_type_label.setText(f"文件类型: {file_ext[1:].upper()}")
    
    def load_recent_files(self):
        """加载最近文件和状态"""
        try:
            if os.path.exists(self.recent_files_file_path):
                with open(self.recent_files_file_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    self.recent_files = data.get('recent_files', [])
                    self.file_states = data.get('file_states', {})
        except Exception as e:
            print(f"加载最近文件失败：{str(e)}")
    
    def save_recent_files(self):
        """保存最近文件和状态"""
        try:
            # 创建数据目录（如果不存在）
            data_dir = os.path.dirname(self.recent_files_file_path)
            os.makedirs(data_dir, exist_ok=True)
            
            data = {
                'recent_files': self.recent_files,
                'file_states': self.file_states
            }
            with open(self.recent_files_file_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存最近文件失败：{str(e)}")
    
    def update_recent_files_menu(self):
        """更新最近文件菜单"""
        self.recent_files_menu.clear()
        
        for file_path in self.recent_files:
            if os.path.exists(file_path):
                # 获取文件名和完整路径
                file_name = os.path.basename(file_path)
                # 获取文件类型图标
                file_ext = os.path.splitext(file_path)[1].lower()
                
                # 根据文件类型设置不同的显示文本
                if file_ext in ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm']:
                    display_text = f"🎥 {file_name}"
                elif file_ext in ['.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma']:
                    display_text = f"🎵 {file_name}"
                elif file_ext in ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.svg', '.ico']:
                    display_text = f"🖼️ {file_name}"
                elif file_ext == '.pdf':
                    display_text = f"📄 {file_name}"
                elif file_ext in ['.epub', '.mobi']:
                    display_text = f"📚 {file_name}"
                elif file_ext in ['.docx', '.xlsx', '.pptx', '.odt', '.ods', '.odp']:
                    display_text = f"📊 {file_name}"
                elif file_ext in ['.txt', '.py', '.html', '.css', '.js', '.json', '.xml', '.yaml', '.yml']:
                    display_text = f"📝 {file_name}"
                else:
                    display_text = f"📁 {file_name}"
                
                # 创建菜单项
                # 创建子菜单用于打开和移除
                file_menu = QMenu(display_text, self)
                
                open_action = QAction("打开", self)
                open_action.setData(file_path)
                open_action.triggered.connect(lambda checked, path=file_path: self.open_recent_file(path))
                file_menu.addAction(open_action)
                
                remove_action = QAction("移除", self)
                remove_action.setData(file_path)
                remove_action.triggered.connect(lambda checked, path=file_path: self.remove_recent_file(path))
                file_menu.addAction(remove_action)
                
                self.recent_files_menu.addMenu(file_menu)
        
        if self.recent_files:
            self.recent_files_menu.addSeparator()
            clear_action = QAction("🗑️ 清除最近文件列表", self)
            clear_action.triggered.connect(self.clear_recent_files)
            self.recent_files_menu.addAction(clear_action)

    def add_recent_file(self, file_path):
        """添加最近文件"""
        if file_path in self.recent_files:
            self.recent_files.remove(file_path)
        self.recent_files.insert(0, file_path)
        
        # 限制最近文件数量
        if len(self.recent_files) > self.max_recent_files:
            self.recent_files.pop()
        
        self.update_recent_files_menu()
        self.save_recent_files()

    def remove_recent_file(self, file_path):
        """移除指定的最近文件"""
        if file_path in self.recent_files:
            self.recent_files.remove(file_path)
            # 如果存在文件状态，也一并移除
            if file_path in self.file_states:
                del self.file_states[file_path]
            self.update_recent_files_menu()
            self.save_recent_files()
            self.statusBar.showMessage(f"已从最近文件列表中移除: {os.path.basename(file_path)}", 3000)
        else:
            self.statusBar.showMessage(f"文件 {os.path.basename(file_path)} 不在最近文件列表中", 3000)
    
    def clear_recent_files(self):
        """清除最近文件列表"""
        self.recent_files.clear()
        self.file_states.clear()
        self.update_recent_files_menu()
        self.save_recent_files()

    def remove_recent_file(self, file_path):
        """移除指定的最近文件"""
        if file_path in self.recent_files:
            self.recent_files.remove(file_path)
            # 如果存在文件状态，也一并移除
            if file_path in self.file_states:
                del self.file_states[file_path]
            self.update_recent_files_menu()
            self.save_recent_files()
            self.statusBar.showMessage(f"已从最近文件列表中移除: {os.path.basename(file_path)}", 3000)
        else:
            self.statusBar.showMessage(f"文件 {os.path.basename(file_path)} 不在最近文件列表中", 3000)
    
    def save_file_state(self, file_path):
        """保存文件状态"""
        # 如果文件状态已存在，先获取现有状态
        if file_path in self.file_states:
            state = self.file_states[file_path]
        else:
            state = {}
            
        # 更新基本状态信息
        state['zoom_factor'] = self.zoom_factor
        state['current_page'] = self.current_page if self.pdf_doc else 0
        
        # 如果是视频或音频文件，保存播放位置
        file_ext = os.path.splitext(file_path)[1].lower()
        video_extensions = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm']
        audio_extensions = ['.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma']
        
        if file_ext in video_extensions or file_ext in audio_extensions:
            state['media_position'] = self.media_player.position()
            state['volume'] = int(self.audio_output.volume() * 100)
        
        # 如果是电子书，保存当前章节、字体大小和阅读模式
        ebook_extensions = ['.epub', '.mobi']
        if file_ext in ebook_extensions:
            state['current_chapter'] = self.current_chapter
            state['font_size'] = self.font_size
            state['read_mode'] = self.read_mode_btn.isChecked()
        
        self.file_states[file_path] = state
        self.save_recent_files()
    
    def restore_file_state(self, file_path):
        """恢复文件状态"""
        if file_path in self.file_states:
            state = self.file_states[file_path]
            self.zoom_factor = state.get('zoom_factor', 1.0)
            self.zoom_slider.setValue(int(self.zoom_factor * 100))
            
            # 恢复PDF页面
            if self.pdf_doc:
                self.current_page = state.get('current_page', 0)
                self.page_combo.setCurrentIndex(self.current_page)
            
            # 恢复视频或音频播放位置
            file_ext = os.path.splitext(file_path)[1].lower()
            video_extensions = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm']
            audio_extensions = ['.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma']
            
            if file_ext in video_extensions or file_ext in audio_extensions:
                media_position = state.get('media_position', 0)
                self.media_player.setPosition(media_position)
                self.video_slider.setValue(media_position)
                
                # 恢复音量
                volume = state.get('volume', 50)
                self.audio_output.setVolume(volume / 100.0)
                if hasattr(self, 'volume_slider'):
                    self.volume_slider.setValue(volume)
            
            # 恢复电子书状态
            ebook_extensions = ['.epub', '.mobi']
            if file_ext in ebook_extensions:
                # 恢复当前章节
                self.current_chapter = state.get('current_chapter', 0)
                if 0 <= self.current_chapter < len(self.chapters):
                    self.chapter_combo.setCurrentIndex(self.current_chapter)
                    self.display_chapter()
                
                # 恢复字体大小
                saved_font_size = state.get('font_size', 16)
                self.font_size = saved_font_size
                self.font_size_slider.setValue(saved_font_size)
                
                # 恢复阅读模式
                read_mode = state.get('read_mode', True)
                self.read_mode_btn.setChecked(read_mode)
                self.toggle_read_mode(read_mode)
    
    def open_file(self):
        """打开文件"""
        # 打开文件对话框
        options = QFileDialog.Option.ReadOnly
        file_path, _ = QFileDialog.getOpenFileName(
            self, "打开文件", "", "所有文件 (*)", options=options
        )
        
        if file_path:
            # 如果有未保存的更改，提示保存
            if hasattr(self, 'text_changed') and self.text_changed:
                reply = QMessageBox.question(
                    self,
                    "保存更改",
                    "当前文件有未保存的更改，是否保存？",
                    QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel
                )
                
                if reply == QMessageBox.StandardButton.Save:
                    if not self.save_file():
                        # 如果保存失败，取消打开新文件
                        return
                elif reply == QMessageBox.StandardButton.Cancel:
                    # 用户取消，不打开新文件
                    return
            
            self.load_file(file_path)
    
    def open_recent_file(self, file_path):
        """打开最近文件"""
        if os.path.exists(file_path):
            # 如果当前窗口已经打开文件，创建新窗口
            if self.current_file:
                # 创建新窗口并加载文件
                new_window = MainWindow()
                new_window.show()
                new_window.load_file(file_path)
                
                # 将新窗口添加到全局窗口列表
                global all_windows
                all_windows.append(new_window)
                
                # 刷新所有窗口的窗口菜单
                for window in all_windows:
                    window.refresh_window_menu()
            else:
                # 在当前窗口打开文件
                self.load_file(file_path)
        else:
            # 文件不存在，从最近文件列表中移除
            QMessageBox.warning(self, "文件不存在", f"文件 {file_path} 不存在或已被移除。")
            self.recent_files.remove(file_path)
            self.update_recent_files_menu()
            self.save_recent_files()
    
    def load_file(self, file_path):
        # 设置当前文件路径
        self.current_file = file_path
        
        # 更新窗口标题
        self.setWindowTitle(f"GoFile - {os.path.basename(file_path)}")
        
        # 断开之前的信号连接
        if hasattr(self, 'text_editor'):
            try:
                self.text_editor.textChanged.disconnect()
            except:
                pass
        
        # 清除之前的预览
        self.text_editor.clear()
        self.image_label.clear()
        self.video_widget.setVisible(False)
        self.media_player.stop()
        
        # 重置控件可见性
        self.zoom_label.setVisible(True)
        self.zoom_out_btn.setVisible(True)
        self.zoom_slider.setVisible(True)
        self.zoom_in_btn.setVisible(True)
        
        # 如果存在音量控制，则隐藏
        if hasattr(self, 'volume_label'):
            self.volume_label.setVisible(False)
        if hasattr(self, 'volume_slider'):
            self.volume_slider.setVisible(False)
        
        # 获取文件扩展名
        file_ext = os.path.splitext(file_path)[1].lower()
        
        try:
            # 扩展文本文件格式支持
            text_extensions = [
                # 普通文本文件
                '.txt', '.log', '.md', '.markdown', '.rst',
                # 配置文件
                '.ini', '.conf', '.config', '.json', '.xml', '.yaml', '.yml',
                # 脚本文件
                '.py', '.js', '.jsx', '.ts', '.tsx', '.php', '.rb', '.sh', '.bat', '.cmd',
                # 网页文件
                '.html', '.htm', '.xhtml', '.css', '.scss', '.sass', '.less',
                # 数据文件
                '.csv', '.tsv', '.sql', '.sqlite',
                # 其他代码文件
                '.java', '.cpp', '.c', '.h', '.hpp', '.cs', '.go', '.rs', '.swift', '.kt',
                # 文档文件
                '.tex', '.latex', '.wiki', '.mdown', '.mdwn', '.mkd', '.mkdn',
                # 其他
                '.diff', '.patch', '.gitignore', '.env'
            ]
            
            # 扩展视频文件格式支持
            video_extensions = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm']
            
            # 新增音乐文件格式支持
            audio_extensions = ['.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma']
            
            # 电子书格式支持
            ebook_extensions = ['.epub', '.mobi']
            
            # Office文档格式支持
            office_extensions = ['.docx', '.xlsx', '.pptx', '.odt', '.ods', '.odp']
            
            if file_ext in video_extensions:
                self.load_video_file(file_path)
            elif file_ext in audio_extensions:
                self.load_audio_file(file_path)
            elif file_ext in text_extensions:
                self.load_text_file(file_path)
            elif file_ext in ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.svg', '.ico']:
                self.load_image_file(file_path)
            elif file_ext == '.pdf':
                self.load_pdf_file(file_path)
            elif file_ext in ebook_extensions:
                self.load_ebook_file(file_path)
            elif file_ext in office_extensions:
                self.load_office_file(file_path)
            else:
                QMessageBox.warning(self, "警告", "不支持的文件类型！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"无法加载文件：{str(e)}")
        
        # 添加到最近文件列表
        self.add_recent_file(file_path)
        
        # 更新状态栏
        self.statusBar.showMessage(f"已打开: {file_path}")
        
        # 刷新所有窗口的窗口菜单
        global all_windows
        for window in all_windows:
            if hasattr(window, 'refresh_window_menu'):
                window.refresh_window_menu()
    
    def load_text_file(self, file_path):
        try:
            detected_encoding = "utf-8"
            try:
                with open(file_path, 'rb') as file:
                    raw_data = file.read(4096)  # 读取前4KB来检测编码
                    result = chardet.detect(raw_data)
                    detected_encoding = result['encoding'] or "utf-8"
            except Exception:
                detected_encoding = "utf-8"
                
            try:
                with open(file_path, 'r', encoding=detected_encoding) as file:
                    content = file.read()
                    
                    # 检测文件类型
                    file_ext = os.path.splitext(file_path)[1].lower()
                    
                    # 检查是否为Markdown文件
                    is_markdown = file_ext in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']
                    
                    # 检查是否为代码文件
                    is_code = self.is_code_file(file_path)
                    
                    if is_markdown:
                        # 使用渲染函数处理Markdown
                        styled_html = self.render_markdown(content)
                        # 设置HTML内容到文本编辑器
                        self.text_editor.setHtml(styled_html)
                    elif is_code:
                        # 使用代码语法高亮
                        styled_html = self.apply_syntax_highlighting(content, file_path)
                        self.text_editor.setHtml(styled_html)
                    else:
                        # 普通文本文件
                        self.text_editor.setText(content)
                        
                    self.text_editor.setVisible(True)
                    self.image_label.setVisible(False)
                    # 设置文本编辑器的字体大小
                    font = self.text_editor.font()
                    font.setPointSize(12)  # 默认字体大小
                    self.text_editor.setFont(font)
                    
                    # 显示编辑模式按钮
                    self.edit_btn.setVisible(True)
                    self.save_btn.setVisible(False)
                    self.is_editing = False
                    self.text_changed = False
                    
                    # 启用保存按钮
                    if hasattr(self, 'save_action'):
                        self.save_action.setEnabled(True)
                    
                    # 连接文本变化信号
                    self.text_editor.textChanged.connect(self.on_text_changed)
                    
                    # 更新状态栏信息
                    self.update_statusbar_for_file_type()
                    self.update_text_file_info(file_path, detected_encoding)
                    self.update_cursor_position()
                    self.update_selection_info()
                    
                    # 在状态栏显示文件类型
                    if is_markdown:
                        self.statusBar.showMessage(f"Markdown文档：{os.path.basename(file_path)}")
                    elif is_code:
                        try:
                            lexer = get_lexer_for_filename(file_path)
                            self.statusBar.showMessage(f"{lexer.name}代码：{os.path.basename(file_path)}")
                        except:
                            self.statusBar.showMessage(f"代码文件：{os.path.basename(file_path)}")
            except UnicodeDecodeError:
                # 如果检测到的编码解码失败，尝试其他编码
                encodings = ['gbk', 'gb2312', 'gb18030', 'big5']
                for encoding in encodings:
                    try:
                        with open(file_path, 'r', encoding=encoding) as file:
                            content = file.read()
                            
                            # 检测文件类型
                            file_ext = os.path.splitext(file_path)[1].lower()
                            
                            # 检查是否为Markdown文件
                            is_markdown = file_ext in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']
                            
                            # 检查是否为代码文件
                            is_code = self.is_code_file(file_path)
                            
                            if is_markdown:
                                # 使用渲染函数处理Markdown
                                styled_html = self.render_markdown(content)
                                # 设置HTML内容到文本编辑器
                                self.text_editor.setHtml(styled_html)
                            elif is_code:
                                # 使用代码语法高亮
                                styled_html = self.apply_syntax_highlighting(content, file_path)
                                self.text_editor.setHtml(styled_html)
                            else:
                                # 普通文本文件
                                self.text_editor.setText(content)
                            
                            self.text_editor.setVisible(True)
                            self.image_label.setVisible(False)
                            # 设置文本编辑器的字体大小
                            font = self.text_editor.font()
                            font.setPointSize(12)  # 默认字体大小
                            self.text_editor.setFont(font)
                            
                            # 显示编辑模式按钮
                            self.edit_btn.setVisible(True)
                            self.save_btn.setVisible(False)
                            self.is_editing = False
                            self.text_changed = False
                            
                            # 连接文本变化信号
                            self.text_editor.textChanged.connect(self.on_text_changed)
                            
                            # 更新状态栏信息
                            detected_encoding = encoding
                            self.update_statusbar_for_file_type()
                            self.update_text_file_info(file_path, detected_encoding)
                            self.update_cursor_position()
                            self.update_selection_info()
                            
                            # 在状态栏显示文件类型
                            if is_markdown:
                                self.statusBar.showMessage(f"Markdown文档：{os.path.basename(file_path)}")
                            elif is_code:
                                try:
                                    lexer = get_lexer_for_filename(file_path)
                                    self.statusBar.showMessage(f"{lexer.name}代码：{os.path.basename(file_path)}")
                                except:
                                    self.statusBar.showMessage(f"代码文件：{os.path.basename(file_path)}")
                            break
                    except UnicodeDecodeError:
                        continue
        except Exception as e:
            QMessageBox.critical(self, "错误", f"无法加载文本文件：{str(e)}")
    
    def is_code_file(self, file_path):
        """检查文件是否为可进行语法高亮的代码文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            bool: 是否为代码文件
        """
        try:
            # 尝试获取文件对应的词法分析器
            get_lexer_for_filename(file_path)
            return True
        except ClassNotFound:
            return False
            
    def apply_syntax_highlighting(self, code, file_path):
        """对代码应用语法高亮
        
        Args:
            code: 代码文本
            file_path: 文件路径，用于确定语言类型
            
        Returns:
            str: 带有语法高亮的HTML
        """
        try:
            # 尝试通过文件名获取合适的词法分析器
            lexer = get_lexer_for_filename(file_path, stripall=True)
            
            # 创建HTML格式化器，设置样式
            formatter = HtmlFormatter(
                style='vs',  # 使用VS代码风格
                linenos=True,  # 显示行号
                cssclass="source",  # CSS类名
                full=False  # 不生成完整的HTML文档
            )
            
            # 应用语法高亮
            highlighted_code = highlight(code, lexer, formatter)
            
            # 完整的HTML文档
            css = formatter.get_style_defs('.source')
            html = f"""
            <html>
            <head>
                <style>
                    body {{
                        font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace;
                        line-height: 1.5;
                        padding: 10px;
                        margin: 0;
                        background-color: #f8f8f8;
                    }}
                    .source {{
                        margin: 0;
                        padding: 0;
                    }}
                    .linenos {{
                        color: #999;
                        padding-right: 10px;
                        border-right: 1px solid #ddd;
                        margin-right: 10px;
                        text-align: right;
                        -webkit-user-select: none;
                        user-select: none;
                    }}
                    {css}
                </style>
            </head>
            <body>
                {highlighted_code}
            </body>
            </html>
            """
            return html
        except ClassNotFound:
            # 如果无法识别文件类型，返回普通文本
            plain_html = f"""
            <html>
            <head>
                <style>
                    body {{
                        font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace;
                        line-height: 1.5;
                        padding: 10px;
                        white-space: pre;
                    }}
                </style>
            </head>
            <body>
                <pre>{code.replace('<', '&lt;').replace('>', '&gt;')}</pre>
            </body>
            </html>
            """
            return plain_html
    
    def on_text_changed(self):
        """文本变更事件处理"""
        # 设置窗口标题以指示未保存状态
        if not self.text_changed:
            self.text_changed = True
            
            if self.current_file:
                self.setWindowTitle(f"GoFile - *{os.path.basename(self.current_file)}")
            else:
                self.setWindowTitle("GoFile - *新文件")
                
            # 更新文本文件信息
            if self.current_file:
                self.update_text_file_info(self.current_file)
            else:
                # 对于新文件，只更新总行数
                doc = self.text_editor.document()
                total_lines = doc.blockCount()
                self.file_info_label.setText(f"总行数: {total_lines} | 大小: 未保存")
            
            # 更新光标位置
            self.update_cursor_position()
    
    def load_image_file(self, file_path):
        try:
            # 使用PIL打开图片并保存原始图片
            self.current_image = Image.open(file_path)
            
            # 获取预览区域的尺寸
            preview_width = self.preview_area.width()
            preview_height = self.preview_area.height()
            
            # 计算合适的缩放比例
            width_ratio = preview_width / self.current_image.width
            height_ratio = preview_height / self.current_image.height
            # 选择较小的比例，确保图片完全显示
            self.zoom_factor = min(width_ratio, height_ratio) * 0.95  # 留出一些边距
            
            # 更新缩放滑动条的值
            self.zoom_slider.setValue(int(self.zoom_factor * 100))
            
            # 更新图片显示
            self.update_image_display()
            
            self.text_editor.setVisible(False)
            self.image_label.setVisible(True)
            
            # 更新状态栏
            self.update_statusbar_for_file_type()
        except Exception as e:
            raise Exception(f"无法加载图片：{str(e)}")
    
    def update_image_display(self):
        """更新图片显示"""
        if not self.current_image:
            return
            
        try:
            # 转换为QPixmap
            qimage = QImage(self.current_image.tobytes(), 
                          self.current_image.width, 
                          self.current_image.height, 
                          self.current_image.width * 3, 
                          QImage.Format.Format_RGB888)
            pixmap = QPixmap.fromImage(qimage)
            
            # 计算缩放后的大小
            scaled_size = QSize(
                int(self.current_image.width * self.zoom_factor),
                int(self.current_image.height * self.zoom_factor)
            )
            
            # 使用更高质量的缩放算法
            scaled_pixmap = pixmap.scaled(
                scaled_size,
                Qt.AspectRatioMode.KeepAspectRatio,
                Qt.TransformationMode.SmoothTransformation
            )
            self.image_label.setPixmap(scaled_pixmap)
            
            # 更新状态栏显示缩放比例
            self.statusBar.showMessage(f"缩放: {int(self.zoom_factor * 100)}%")
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"无法更新图片显示：{str(e)}")
    
    def load_pdf_file(self, file_path):
        try:
            # 关闭之前的PDF文档
            if self.pdf_doc:
                try:
                    self.pdf_doc.close()
                except Exception as e:
                    print(f"关闭PDF文档失败：{str(e)}")
                finally:
                    self.pdf_doc = None
            
            # 打开新的PDF文件
            if not os.path.exists(file_path):
                raise Exception(f"文件不存在：{file_path}")
                
            self.pdf_doc = fitz.open(file_path)
            
            # 确保PDF文档有效
            if not self.pdf_doc or self.pdf_doc.page_count == 0:
                raise Exception("无效的PDF文档或PDF文档没有页面")
            
            # 先恢复保存的状态
            if file_path in self.file_states:
                state = self.file_states[file_path]
                self.current_page = state.get('current_page', 0)
                self.zoom_factor = state.get('zoom_factor', 1.0)
                self.zoom_slider.setValue(int(self.zoom_factor * 100))
            else:
                self.current_page = 0
                self.zoom_factor = 1.0
            
            # 确保当前页在有效范围内
            if self.current_page < 0 or self.current_page >= len(self.pdf_doc):
                self.current_page = 0
            
            # 清空缩略图列表
            self.thumbnail_list.clear()
            
            # 更新页面显示
            self.update_pdf_page()
            
            # 更新页码选择器
            self.update_page_selector()
            
            # 生成缩略图
            self.generate_thumbnails()
            
            # 显示PDF控制器
            self.page_label.setVisible(True)
            self.page_combo.setVisible(True)
            self.thumbnail_btn.setVisible(True)
            
            self.text_editor.setVisible(False)
            self.image_label.setVisible(True)
            
            # 更新状态栏
            self.update_statusbar_for_file_type()
            
        except Exception as e:
            # 确保发生异常时重置PDF文档
            self.pdf_doc = None
            
            # 恢复UI状态
            self.page_label.setVisible(False)
            self.page_combo.setVisible(False)
            self.thumbnail_btn.setVisible(False)
            self.image_label.clear()
            
            # 显示友好的错误信息
            QMessageBox.warning(self, "警告", f"无法加载PDF：{str(e)}")
            print(f"PDF加载错误：{str(e)}")
            return False
            
        return True
    
    def update_page_selector(self):
        """更新页码选择器"""
        if not self.pdf_doc:
            return
            
        # 暂时断开信号连接，防止触发页面更改事件
        self.page_combo.blockSignals(True)
        self.page_combo.clear()
        
        # 添加所有页码
        for i in range(len(self.pdf_doc)):
            self.page_combo.addItem(f"第 {i+1} 页")
        
        # 设置当前页
        self.page_combo.setCurrentIndex(self.current_page)
        
        # 重新连接信号
        self.page_combo.blockSignals(False)
    
    def page_changed(self, index):
        """页码选择改变时的处理"""
        if index != self.current_page:
            self.current_page = index
            self.update_pdf_page()
    
    def generate_thumbnails(self):
        """生成PDF缩略图"""
        if not self.pdf_doc:
            return
            
        try:
            self.thumbnail_list.clear()
            
            # 对每页生成缩略图，使用异常处理包装每一页的处理
            for i in range(len(self.pdf_doc)):
                try:
                    # 获取页面
                    page = self.pdf_doc[i]
                    if page is None:
                        print(f"无法获取第 {i+1} 页进行缩略图生成")
                        continue
                    
                    # 生成缩略图
                    thumb_mat = fitz.Matrix(0.2, 0.2)  # 20%大小
                    thumb_pix = page.get_pixmap(matrix=thumb_mat, alpha=False)
                    
                    # 检查pixmap是否有效
                    if not thumb_pix or thumb_pix.width <= 0 or thumb_pix.height <= 0:
                        print(f"第 {i+1} 页生成的缩略图无效")
                        continue
                        
                    # 转换为QImage和QPixmap
                    thumb_qimage = QImage(thumb_pix.samples, thumb_pix.width, thumb_pix.height, 
                                      thumb_pix.stride, QImage.Format.Format_RGB888)
                        
                    if thumb_qimage.isNull():
                        print(f"第 {i+1} 页无法创建缩略图QImage")
                        continue
                            
                    thumb_pixmap = QPixmap.fromImage(thumb_qimage)
                    
                    if thumb_pixmap.isNull():
                        print(f"第 {i+1} 页无法创建缩略图QPixmap")
                        continue
                        
                    # 创建列表项
                    item = QListWidgetItem()
                    item.setIcon(QIcon(thumb_pixmap))
                    item.setText(f"第 {i+1} 页")
                    item.setData(Qt.ItemDataRole.UserRole, i)  # 存储页码索引
                    self.thumbnail_list.addItem(item)
                        
                except Exception as e:
                    # 单个页面的缩略图生成失败不应该导致整个过程失败
                    print(f"生成第 {i+1} 页缩略图失败：{str(e)}")
                    continue
                    
        except Exception as e:
            # 捕获整个缩略图生成过程中的异常
            print(f"生成缩略图过程出错：{str(e)}")
            # 不弹出错误对话框，只在控制台打印错误信息
            # 因为缩略图失败不应该中断用户体验
    
    def thumbnail_clicked(self, item):
        """点击缩略图时的处理"""
        try:
            if not item or not self.pdf_doc:
                return
                
            page_index = item.data(Qt.ItemDataRole.UserRole)
                
            # 检查页码是否有效
            if page_index is None or page_index < 0 or page_index >= len(self.pdf_doc):
                print(f"缩略图点击：无效的页码索引 {page_index}")
                return
                
            if page_index != self.current_page:
                self.current_page = page_index
                self.page_combo.setCurrentIndex(page_index)
                self.update_pdf_page()
                
        except Exception as e:
            print(f"缩略图点击处理出错：{str(e)}")
            # 不显示错误对话框，避免干扰用户体验
    
    def toggle_thumbnails(self, checked):
        """切换缩略图面板显示状态"""
        self.thumbnails_widget.setVisible(checked)
        
        # 调整分割器大小
        if checked:
            self.splitter.setSizes([200, self.width() - 200])
        else:
            self.splitter.setSizes([0, self.width()])
    
    def update_pdf_page(self):
        if not self.pdf_doc:
            return
            
        try:
            # 确保当前页在有效范围内
            if self.current_page < 0 or self.current_page >= len(self.pdf_doc):
                self.current_page = 0
                
            # 检查PDF文档是否有效
            if self.pdf_doc.page_count == 0:
                raise Exception("PDF文档没有页面")
                
            # 获取当前页
            page = self.pdf_doc[self.current_page]
            if page is None:
                raise Exception(f"无法获取第 {self.current_page + 1} 页")
            
            # 设置更高的DPI和更好的渲染质量
            base_zoom = 4.0  # 提高基础分辨率
            zoom = base_zoom * self.zoom_factor
            mat = fitz.Matrix(zoom, zoom)
            
            # 创建pixmap时包含异常处理
            try:
                pix = page.get_pixmap(matrix=mat, alpha=False)
            except Exception as e:
                raise Exception(f"无法渲染页面：{str(e)}")
            
            # 检查pixmap是否有效
            if not pix or pix.width <= 0 or pix.height <= 0:
                raise Exception("无效的页面图像")
                
            # 安全地转换为QImage
            try:
                qimage = QImage(pix.samples, pix.width, pix.height, pix.stride, QImage.Format.Format_RGB888)
                if qimage.isNull():
                    raise Exception("无法创建图像")
                    
                pixmap = QPixmap.fromImage(qimage)
                if pixmap.isNull():
                    raise Exception("无法创建pixmap")
            except Exception as e:
                raise Exception(f"图像转换失败：{str(e)}")
            
            # 使用更高质量的缩放算法设置图像
            self.image_label.setPixmap(pixmap)
            
            # 更新状态栏信息
            self.statusBar.showMessage(f"第 {self.current_page + 1}/{len(self.pdf_doc)} 页 - 缩放: {int(self.zoom_factor * 100)}%")
            
        except Exception as e:
            print(f"PDF页面渲染错误：{str(e)}")
            # 使用QMessageBox.warning而不是critical，减轻错误的严重性
            # 这样可以防止在某些情况下应用程序意外关闭
            QMessageBox.warning(self, "警告", f"无法加载PDF页面：{str(e)}")
            
            # 如果发生异常，尝试恢复到安全状态
            try:
                self.image_label.clear()
                self.statusBar.showMessage("PDF页面加载失败")
            except:
                pass  # 忽略在恢复过程中的任何错误

    def zoom_in(self):
        """放大"""
        current = self.zoom_slider.value()
        self.zoom_slider.setValue(min(current + 10, 500))
    
    def zoom_out(self):
        """缩小"""
        current = self.zoom_slider.value()
        self.zoom_slider.setValue(max(current - 10, 10))
    
    def on_zoom_changed(self, value):
        """处理缩放值变化"""
        self.zoom_factor = value / 100.0
        self.zoom_label.setText(f"{value}%")
        
        if self.pdf_doc:
            self.update_pdf_page()
        elif self.current_image:
            self.update_image_display()
        elif self.text_editor.isVisible():
            # 更新文本编辑器的字体大小
            font = self.text_editor.font()
            base_size = 12  # 基础字体大小
            new_size = int(base_size * self.zoom_factor)
            font.setPointSize(new_size)
            self.text_editor.setFont(font)
            
        # 更新状态栏显示缩放比例
        self.statusBar.showMessage(f"缩放: {value}%")

    def wheelEvent(self, event):
        """处理鼠标滚轮事件"""
        # PDF和图片的缩放处理
        if (self.pdf_doc or self.current_image) and event.modifiers() == Qt.KeyboardModifier.ControlModifier:
            # 获取滚轮滚动的角度，正数表示向上滚动，负数表示向下滚动
            delta = event.angleDelta().y()
            
            # 获取当前缩放值
            current = self.zoom_slider.value()
            
            # 计算新的缩放值
            if delta > 0:
                # 向上滚动，放大
                new_value = min(current + 10, 500)
            else:
                # 向下滚动，缩小
                new_value = max(current - 10, 10)
            
            # 更新缩放标签
            self.zoom_label.setText(f"{new_value}%")
            
            # 更新滑动条值（这会触发on_zoom_changed）
            self.zoom_slider.setValue(new_value)
            
            # 阻止事件继续传播
            event.accept()
        # 中央歌词字体大小调整
        elif hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible() and event.modifiers() == Qt.KeyboardModifier.ControlModifier:
            # 获取滚轮滚动的角度，正数表示向上滚动，负数表示向下滚动
            delta = event.angleDelta().y()
            
            if delta > 0:
                # 向上滚动，放大字体
                if self.center_lyrics_font_size < self.center_lyrics_font_size_max:
                    self.center_lyrics_font_size += 1
                    self.update_center_lyrics_font_size()
                    # 如果有选中的歌词，确保其可见
                    if self.current_lyric_index >= 0:
                        self.update_center_lyric_highlight(self.current_lyric_index)
            else:
                # 向下滚动，缩小字体
                if self.center_lyrics_font_size > self.center_lyrics_font_size_min:
                    self.center_lyrics_font_size -= 1
                    self.update_center_lyrics_font_size()
                    # 如果有选中的歌词，确保其可见
                    if self.current_lyric_index >= 0:
                        self.update_center_lyric_highlight(self.current_lyric_index)
            
            # 阻止事件继续传播
            event.accept()
        else:
            # 如果没有按住Ctrl键，则调用父类的滚轮事件处理（用于正常滚动）
            super().wheelEvent(event)

    def mousePressEvent(self, event):
        """处理鼠标按下事件"""
        try:
            # 检查是否是PDF文档和左键点击
            if event.button() == Qt.MouseButton.LeftButton and self.current_image:
                # 处理图片的拖动
                # 检查是否有滚动条可见
                h_scrollbar = self.preview_area.horizontalScrollBar()
                v_scrollbar = self.preview_area.verticalScrollBar()
                has_scrollbar = (h_scrollbar.isVisible() and h_scrollbar.maximum() > 0) or \
                            (v_scrollbar.isVisible() and v_scrollbar.maximum() > 0)
                
                # 只有当有滚动条可见时才允许拖动
                if has_scrollbar:
                    self.is_dragging = True
                    self.drag_start_pos = event.pos()
                    self.scroll_start_pos = QPoint(
                        h_scrollbar.value(),
                        v_scrollbar.value()
                    )
                    self.setCursor(Qt.CursorShape.ClosedHandCursor)
            # 检查是否是PDF文档和左键点击 - 仅允许拖动滚动，不响应点击事件
            elif event.button() == Qt.MouseButton.LeftButton and self.pdf_doc:
                # 首先确保PDF文档有效
                if self.current_page < 0 or self.current_page >= len(self.pdf_doc):
                    # 页码无效，重置页码
                    self.current_page = 0
                    self.update_pdf_page()
                
                # 检查是否有滚动条可见
                h_scrollbar = self.preview_area.horizontalScrollBar()
                v_scrollbar = self.preview_area.verticalScrollBar()
                has_scrollbar = (h_scrollbar.isVisible() and h_scrollbar.maximum() > 0) or \
                            (v_scrollbar.isVisible() and v_scrollbar.maximum() > 0)
                
                # 只有当有滚动条可见时才允许拖动，但不执行其他点击操作
                if has_scrollbar:
                    self.is_dragging = True
                    self.drag_start_pos = event.pos()
                    self.scroll_start_pos = QPoint(
                        h_scrollbar.value(),
                        v_scrollbar.value()
                    )
                    self.setCursor(Qt.CursorShape.ClosedHandCursor)
                # 对于PDF文件，阻止事件传递给父类以防止点击操作
                event.accept()
                return
            
            # 调用父类方法
            super().mousePressEvent(event)
            
        except Exception as e:
            # 捕获任何可能的异常，防止应用崩溃
            print(f"鼠标点击事件处理出错：{str(e)}")
            # 重置状态以确保应用程序能够继续运行
            self.is_dragging = False
            self.drag_start_pos = None
            self.scroll_start_pos = None
            self.setCursor(Qt.CursorShape.ArrowCursor)

    def mouseMoveEvent(self, event):
        """处理鼠标移动事件"""
        if self.is_dragging and self.drag_start_pos:
            # 计算移动距离
            delta = event.pos() - self.drag_start_pos
            h_scrollbar = self.preview_area.horizontalScrollBar()
            v_scrollbar = self.preview_area.verticalScrollBar()
            
            # 只在对应的滚动条可见时更新位置
            if h_scrollbar.isVisible() and h_scrollbar.maximum() > 0:
                h_scrollbar.setValue(self.scroll_start_pos.x() - delta.x())
            if v_scrollbar.isVisible() and v_scrollbar.maximum() > 0:
                v_scrollbar.setValue(self.scroll_start_pos.y() - delta.y())
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        """处理鼠标释放事件"""
        if event.button() == Qt.MouseButton.LeftButton and self.is_dragging:
            self.is_dragging = False
            self.drag_start_pos = None
            self.scroll_start_pos = None
            self.setCursor(Qt.CursorShape.ArrowCursor)
        super().mouseReleaseEvent(event)

    def handle_scroll(self, value):
        """处理滚动事件，用于自动翻页"""
        if not self.pdf_doc or self.is_page_turning:
            return
            
        v_scrollbar = self.preview_area.verticalScrollBar()
        
        # 检查是否滚动到底部或顶部
        if value >= v_scrollbar.maximum() and self.current_page < len(self.pdf_doc) - 1:
            # 滚动到底部，加载下一页
            self.is_page_turning = True  # 防止页面切换时触发滚动事件
            self.current_page += 1
            self.page_combo.setCurrentIndex(self.current_page)  # 更新页码选择器
            self.update_pdf_page()
            # 滚动到页面顶部
            v_scrollbar.setValue(0)
            self.is_page_turning = False
        elif value <= v_scrollbar.minimum() and self.current_page > 0:
            # 滚动到顶部，加载上一页
            self.is_page_turning = True  # 防止页面切换时触发滚动事件
            self.current_page -= 1
            self.page_combo.setCurrentIndex(self.current_page)  # 更新页码选择器
            self.update_pdf_page()
            # 滚动到页面底部
            v_scrollbar.setValue(v_scrollbar.maximum())
            self.is_page_turning = False

    def closeEvent(self, event):
        """窗口关闭事件处理，保存播放列表和当前状态"""
        # 如果系统托盘可用且窗口不是被强制关闭，则最小化到托盘
        if (hasattr(self, 'system_integration') and 
            self.system_integration and 
            self.system_integration.tray_icon and 
            self.system_integration.tray_icon.isVisible() and
            not getattr(self, '_force_close', False)):
            
            # 隐藏窗口到系统托盘
            self.hide()
            if self.system_integration:
                self.system_integration.show_tray_message(
                    "GoFile", 
                    "应用程序已最小化到系统托盘"
                )
            event.ignore()
            return
        
        # 停止视频播放
        if hasattr(self, 'media_player') and self.media_player.playbackState() != QMediaPlayer.PlaybackState.StoppedState:
            self.media_player.stop()
        
        # 检查是否有未保存的修改
        if hasattr(self, 'text_modified') and self.text_modified:
            reply = QMessageBox.question(
                self,
                "保存更改",
                "文件已被修改，是否保存更改？",
                QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel
            )
            
            if reply == QMessageBox.StandardButton.Save:
                if not self.save_file():
                    event.ignore()
                    return
            elif reply == QMessageBox.StandardButton.Cancel:
                event.ignore()
                return
        
        # 保存当前文件状态
        if self.current_file:
            try:
                self.save_file_state(self.current_file)
            except Exception as e:
                print(f"保存文件状态失败: {str(e)}")
        
        # 保存当前歌词和歌词数据
        try:
            self.save_current_lyrics()
            self.save_lyrics()
        except Exception as e:
            print(f"保存歌词失败: {str(e)}")
        
        # 保存播放列表
        try:
            self.save_playlist()
        except Exception as e:
            print(f"保存播放列表失败: {str(e)}")
        
        # 保存最近文件
        try:
            self.save_recent_files()
        except Exception as e:
            print(f"保存最近文件失败: {str(e)}")
        
        # 从窗口列表中移除此窗口
        global all_windows
        if self in all_windows:
            all_windows.remove(self)
        
        # 更新其他窗口的窗口菜单
        for window in all_windows:
            if window != self and window.isVisible():
                try:
                    window.refresh_window_menu()
                except:
                    pass  # 防止任何异常
        
        # 只有在没有可见窗口时才退出应用程序
        visible_windows = [w for w in all_windows if w.isVisible()]
        if not visible_windows:
            print("所有窗口已关闭，退出应用程序")
            # 稍微延迟退出，确保当前窗口已完全关闭
            QTimer.singleShot(100, QApplication.quit)
        
        # 接受关闭事件
        event.accept()
        
    def resizeEvent(self, event):
        """窗口大小改变事件处理"""
        super().resizeEvent(event)
        # 如果当前是音乐文件并且显示的是封面，更新封面大小
        if hasattr(self, 'current_file') and self.current_file and hasattr(self, 'image_label') and self.image_label.isVisible():
            file_ext = os.path.splitext(self.current_file)[1].lower()
            audio_extensions = ['.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma']
            if file_ext in audio_extensions:
                # 延迟执行，以确保窗口大小已经更新
                QTimer.singleShot(100, lambda: self.display_audio_cover(self.current_file))
        
    def toggle_fullscreen(self):
        """切换全屏状态"""
        if self.isFullScreen():
            self.showNormal()
            self.toggle_fullscreen_action.setText("切换全屏(&F)")
        else:
            self.showFullScreen()
            self.toggle_fullscreen_action.setText("退出全屏(&F)")
    
    def keyPressEvent(self, event):
        """处理按键事件"""
        # 处理ESC键退出全屏
        if event.key() == Qt.Key.Key_Escape and self.isFullScreen():
            self.showNormal()
            self.toggle_fullscreen_action.setText("切换全屏(&F)")
        # 处理中央歌词字体大小重置
        elif hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
            # 重置中央歌词字体大小 (Ctrl+0)
            if event.modifiers() == Qt.KeyboardModifier.ControlModifier and event.key() == Qt.Key.Key_0:
                self.center_lyrics_font_size = 16  # 恢复默认大小
                self.update_center_lyrics_font_size()
                # 如果有选中的歌词，确保其可见
                if self.current_lyric_index >= 0:
                    self.update_center_lyric_highlight(self.current_lyric_index)
                event.accept()
                return
                
        # 其他按键处理委托给父类
        super().keyPressEvent(event)

    def toggle_edit_mode(self, checked):
        """切换编辑模式"""
        # 检查是否为文本文件
        if self.current_file:
            file_ext = os.path.splitext(self.current_file)[1].lower()
            
            # 如果是Markdown文件，使用分屏预览模式
            if file_ext in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']:
                self.toggle_markdown_preview_mode()
                return
                
            text_extensions = [
                # 普通文本文件
                '.txt', '.log', '.rst',
                # 配置文件
                '.ini', '.conf', '.config', '.json', '.xml', '.yaml', '.yml',
                # 脚本文件
                '.py', '.js', '.jsx', '.ts', '.tsx', '.php', '.rb', '.sh', '.bat', '.cmd',
                # 网页文件
                '.html', '.htm', '.xhtml', '.css', '.scss', '.sass', '.less',
                # 数据文件
                '.csv', '.tsv', '.sql', '.sqlite',
                # 其他代码文件
                '.java', '.cpp', '.c', '.h', '.hpp', '.cs', '.go', '.rs', '.swift', '.kt',
                # 文档文件
                '.tex', '.latex', '.wiki',
                # 其他
                '.diff', '.patch', '.gitignore', '.env'
            ]
            
            if file_ext not in text_extensions:
                QMessageBox.warning(self, "警告", "只有文本类型的文件才能进入编辑模式！")
                self.edit_btn.setChecked(False)
                return
            
            # 检查是否为Markdown文件，如果是，需要特殊处理
            is_markdown = file_ext in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']
            
            # 检查是否为代码文件
            is_code = self.is_code_file(self.current_file)
            
            if (is_markdown or is_code) and checked:
                # 警告用户切换到编辑模式将显示原始文本
                content_type = "Markdown" if is_markdown else "代码"
                reply = QMessageBox.question(
                    self,
                    f"编辑{content_type}",
                    f"切换到编辑模式将显示原始{content_type}文本。继续？",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
                )
                
                if reply == QMessageBox.StandardButton.No:
                    self.edit_btn.setChecked(False)
                    return
                
                # 从文件中读取原始内容
                try:
                    with open(self.current_file, 'r', encoding='utf-8') as file:
                        content = file.read()
                        self.text_editor.setText(content)
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"无法读取文件：{str(e)}")
                    self.edit_btn.setChecked(False)
                    return
            elif is_markdown and not checked:
                # 从编辑模式切换回查看模式时，重新渲染Markdown
                content = self.text_editor.toPlainText()
                styled_html = self.render_markdown(content)
                self.text_editor.setHtml(styled_html)
            elif is_code and not checked:
                # 从编辑模式切换回查看模式时，重新应用语法高亮
                content = self.text_editor.toPlainText()
                styled_html = self.apply_syntax_highlighting(content, self.current_file)
                self.text_editor.setHtml(styled_html)
        
        self.is_editing = checked
        self.text_editor.setReadOnly(not checked)
        self.save_btn.setVisible(checked)
        
        # 更新编辑菜单状态
        self.undo_action.setEnabled(checked)
        self.redo_action.setEnabled(checked)
        self.cut_action.setEnabled(checked)
        self.paste_action.setEnabled(checked)
        self.delete_action.setEnabled(checked)
        self.replace_action.setEnabled(checked)
        
        if not checked:
            self.text_changed = False
            if self.current_file:
                self.setWindowTitle(f"GoFile - {os.path.basename(self.current_file)}")

    def save_file(self):
        """保存文件"""
        if not self.current_file or (not self.is_editing and not self.markdown_preview_mode):
            return self.save_file_as()
        
        # 检查是否为文本文件
        file_ext = os.path.splitext(self.current_file)[1].lower()
        text_extensions = [
            # 普通文本文件
            '.txt', '.log', '.md', '.markdown', '.rst',
            # 配置文件
            '.ini', '.conf', '.config', '.json', '.xml', '.yaml', '.yml',
            # 脚本文件
            '.py', '.js', '.jsx', '.ts', '.tsx', '.php', '.rb', '.sh', '.bat', '.cmd',
            # 网页文件
            '.html', '.htm', '.xhtml', '.css', '.scss', '.sass', '.less',
            # 数据文件
            '.csv', '.tsv', '.sql', '.sqlite',
            # 其他代码文件
            '.java', '.cpp', '.c', '.h', '.hpp', '.cs', '.go', '.rs', '.swift', '.kt',
            # 文档文件
            '.tex', '.latex', '.wiki', '.mdown', '.mdwn', '.mkd', '.mkdn',
            # 其他
            '.diff', '.patch', '.gitignore', '.env'
        ]
        
        if file_ext not in text_extensions:
            QMessageBox.warning(self, "警告", "只有文本类型的文件才能保存！")
            return False
        
        try:
            # 根据当前模式获取内容
            if self.markdown_preview_mode:
                content = self.markdown_editor.toPlainText()
            else:
                content = self.text_editor.toPlainText()
                
            with open(self.current_file, 'w', encoding='utf-8') as file:
                file.write(content)
            self.text_changed = False
            self.setWindowTitle(f"GoFile - {os.path.basename(self.current_file)}")
            self.statusBar.showMessage(f"文件已保存: {self.current_file}")
            
            # 更新文件信息
            self.update_text_file_info(self.current_file, "utf-8")
            
            # 如果是Markdown分屏预览模式，保存后更新预览
            if self.markdown_preview_mode:
                styled_html = self.render_markdown(content)
                self.markdown_preview.setHtml(styled_html)
                self.statusBar.showMessage(f"Markdown文档已保存: {self.current_file}")
            # 如果是Markdown文件且不在编辑模式，保存后重新渲染
            elif not self.is_editing:
                is_markdown = file_ext in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']
                is_code = self.is_code_file(self.current_file)
                
                if is_markdown:
                    styled_html = self.render_markdown(content)
                    self.text_editor.setHtml(styled_html)
                    self.statusBar.showMessage(f"Markdown文档已保存并重新渲染: {self.current_file}")
                elif is_code:
                    styled_html = self.apply_syntax_highlighting(content, self.current_file)
                    self.text_editor.setHtml(styled_html)
                    self.statusBar.showMessage(f"代码文件已保存并重新高亮: {self.current_file}")
            
            # 刷新所有窗口的窗口菜单
            global all_windows
            for window in all_windows:
                if hasattr(window, 'refresh_window_menu'):
                    window.refresh_window_menu()
            
            return True
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存文件失败：{str(e)}")
            return False

    def save_file_as(self):
        """另存为"""
        if not hasattr(self, 'text_editor') or not self.text_editor.isVisible():
            QMessageBox.warning(self, "警告", "只有文本类型的文件才能保存！")
            return False
        
        options = QFileDialog.Option.ReadOnly
        if self.current_file:
            initial_dir = os.path.dirname(self.current_file)
            suggested_name = os.path.basename(self.current_file)
        else:
            initial_dir = os.path.expanduser("~")
            suggested_name = "新文件.txt"
            
        file_path, _ = QFileDialog.getSaveFileName(
            self, "另存为", os.path.join(initial_dir, suggested_name),
            "文本文件 (*.txt);;所有文件 (*)", options=options
        )
        
        if not file_path:
            return False
            
        try:
            content = self.text_editor.toPlainText()
            with open(file_path, 'w', encoding='utf-8') as file:
                file.write(content)
                
            self.current_file = file_path
            self.text_changed = False
            self.setWindowTitle(f"GoFile - {os.path.basename(file_path)}")
            
            # 添加到最近文件列表
            self.add_recent_file(file_path)
            
            # 更新文件信息
            self.update_text_file_info(file_path, "utf-8")
            
            # 刷新所有窗口的窗口菜单
            global all_windows
            for window in all_windows:
                if hasattr(window, 'refresh_window_menu'):
                    window.refresh_window_menu()
            
            return True
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存文件失败：{str(e)}")
            return False

    def new_file(self):
        """创建新文件"""
        # 如果已经有未保存的更改，提示保存
        if hasattr(self, 'text_changed') and self.text_changed:
            reply = QMessageBox.question(
                self,
                "保存更改",
                "当前文件有未保存的更改，是否保存？",
                QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel
            )
            
            if reply == QMessageBox.StandardButton.Save:
                if not self.save_file():
                    # 如果保存失败，取消新建文件
                    return
            elif reply == QMessageBox.StandardButton.Cancel:
                # 用户取消，不创建新文件
                return
        
        # 创建新文本文件
        self.current_file = None
        self.text_editor.clear()
        self.text_editor.setVisible(True)
        self.image_label.setVisible(False)
        self.is_editing = True
        self.text_changed = False
        self.text_editor.setReadOnly(False)
        
        # 连接文本变化信号
        try:
            self.text_editor.textChanged.disconnect()
        except:
            pass
        self.text_editor.textChanged.connect(self.on_text_changed)
        
        # 显示编辑模式按钮和保存按钮
        self.edit_btn.setVisible(True)
        self.edit_btn.setChecked(True)
        self.save_btn.setVisible(True)
        
        # 更新状态栏
        self.statusBar.showMessage("新建文件")
        
        # 更新窗口标题
        self.setWindowTitle("GoFile - 新建文件")
        
        # 更新状态栏
        self.update_statusbar_for_file_type()
        
        # 刷新所有窗口的窗口菜单
        global all_windows
        for window in all_windows:
            if hasattr(window, 'refresh_window_menu'):
                window.refresh_window_menu()

    def load_video_file(self, file_path):
        """加载视频文件"""
        try:
            # 设置视频源
            self.media_player.setSource(QUrl.fromLocalFile(file_path))
            
            # 显示视频控件
            self.video_widget.setVisible(True)
            self.play_btn.setVisible(True)
            self.video_slider.setVisible(True)
            
            # 隐藏其他控件
            self.text_editor.setVisible(False)
            self.image_label.setVisible(False)
            
            # 隐藏缩放控件
            self.zoom_label.setVisible(False)
            self.zoom_out_btn.setVisible(False)
            self.zoom_slider.setVisible(False)
            self.zoom_in_btn.setVisible(False)
            
            # 创建音量控制
            if not hasattr(self, 'volume_label'):
                self.volume_label = QLabel("音量")
                self.volume_label.setFixedWidth(50)
                self.volume_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                # 将音量标签插入到播放按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.play_btn) + 1, self.volume_label)
            
            if not hasattr(self, 'volume_slider'):
                self.volume_slider = QSlider(Qt.Orientation.Horizontal)
                self.volume_slider.setMinimum(0)
                self.volume_slider.setMaximum(100)
                self.volume_slider.setValue(50)  # 默认音量50%
                self.volume_slider.setFixedWidth(100)
                self.volume_slider.valueChanged.connect(self.on_volume_changed)
                # 将音量滑动条插入到音量标签后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.volume_label) + 1, self.volume_slider)
            
            # 创建视频时间显示标签
            if not hasattr(self, 'audio_time_label'):
                self.audio_time_label = QLabel("00:00 / 00:00")
                self.audio_time_label.setFixedWidth(120)
                self.audio_time_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                # 将时间标签插入到视频滑动条后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.video_slider) + 1, self.audio_time_label)
            
            # 显示时间标签和音量控制
            self.audio_time_label.setVisible(True)
            self.volume_label.setVisible(True)
            self.volume_slider.setVisible(True)
            
            # 连接媒体播放器信号
            self.media_player.positionChanged.connect(self.position_changed)
            self.media_player.durationChanged.connect(self.duration_changed)
            self.media_player.playbackStateChanged.connect(self.state_changed)
            
            # 设置初始状态
            self.is_playing = False
            self.play_btn.setText("播放")
            
            # 恢复保存的播放位置
            self.restore_file_state(file_path)
            
            # 更新状态栏
            self.update_statusbar_for_file_type()
            
        except Exception as e:
            raise Exception(f"无法加载视频：{str(e)}")

    def on_volume_changed(self, value):
        """处理音量变化"""
        self.audio_output.setVolume(value / 100.0)
        self.statusBar.showMessage(f"音量: {value}%")

    def toggle_play(self):
        """切换媒体播放/暂停状态"""
        if self.is_playing:
            self.media_player.pause()
            self.play_btn.setText("播放")
        else:
            self.media_player.play()
            self.play_btn.setText("暂停")
        self.is_playing = not self.is_playing

    def position_changed(self, position):
        """媒体播放位置变化时的处理
        
        Args:
            position: 当前播放位置（毫秒）
        """
        # 更新进度条位置
        self.video_slider.setValue(position)
        
        # 更新时间显示
        if hasattr(self, 'audio_time_label'):
            total_duration = self.media_player.duration()
            current_time = self.format_duration(position)
            total_time = self.format_duration(total_duration)
            self.audio_time_label.setText(f"{current_time} / {total_time}")
        
        # 更新当前歌词
        self.update_current_lyric(position)
        
        # 如果在同步模式下，更新同步状态显示
        if hasattr(self, 'sync_lyrics_btn') and self.sync_lyrics_btn.isChecked():
            self.update_sync_status(position)

    def duration_changed(self, duration):
        """媒体总时长改变时的处理"""
        # 设置滑动条范围
        self.video_slider.setRange(0, duration)
        
        # 如果音频时间标签存在且可见，则更新时间显示
        if hasattr(self, 'audio_time_label') and self.audio_time_label.isVisible():
            current_time = self.format_duration(self.media_player.position())
            total_time = self.format_duration(duration)
            self.audio_time_label.setText(f"{current_time} / {total_time}")

    def set_video_position(self, position):
        """设置媒体播放位置"""
        self.media_player.setPosition(position)
        
        # 如果音频时间标签存在且可见，则更新时间显示
        if hasattr(self, 'audio_time_label') and self.audio_time_label.isVisible():
            current_time = self.format_duration(position)
            total_time = self.format_duration(self.media_player.duration())
            self.audio_time_label.setText(f"{current_time} / {total_time}")

    def state_changed(self, state):
        """媒体播放状态改变时的处理"""
        if state == QMediaPlayer.PlaybackState.StoppedState:
            self.is_playing = False
            self.play_btn.setText("播放")
            self.video_slider.setValue(0)
            
            # 如果音频时间标签存在且可见，重置时间显示
            if hasattr(self, 'audio_time_label') and self.audio_time_label.isVisible():
                self.audio_time_label.setText("00:00 / 00:00")

    def load_ebook_file(self, file_path):
        """加载电子书文件"""
        try:
            # 关闭之前的电子书
            if self.ebook_doc:
                self.ebook_doc = None
            
            # 获取文件扩展名
            file_ext = os.path.splitext(file_path)[1].lower()
            
            if file_ext == '.epub':
                # 加载EPUB文件
                self.ebook_doc = ebooklib.epub.read_epub(file_path)
                self.chapters = []
                self.chapter_titles = []
                
                # 提取章节
                for item in self.ebook_doc.get_items():
                    if item.get_type() == ebooklib.ITEM_DOCUMENT:
                        # 解析HTML内容
                        content = item.get_content().decode('utf-8')
                        soup = BeautifulSoup(content, 'html.parser')
                        
                        # 尝试获取章节标题
                        title = None
                        h_tags = soup.find(['h1', 'h2', 'h3', 'h4'])
                        if h_tags:
                            title = h_tags.get_text(strip=True)
                        
                        # 如果没有找到标题，使用默认标题
                        if not title:
                            title = f"第 {len(self.chapters) + 1} 章"
                        
                        # 获取正文内容
                        # 移除script和style标签
                        for tag in soup(['script', 'style']):
                            tag.decompose()
                        
                        # 处理段落
                        paragraphs = []
                        for p in soup.find_all(['p', 'div']):
                            text = p.get_text(strip=True)
                            if text:  # 只添加非空段落
                                paragraphs.append(text)
                        
                        # 将段落组合成章节内容
                        chapter_content = '\n\n'.join(paragraphs)
                        if chapter_content.strip():  # 只添加非空章节
                            self.chapters.append(chapter_content)
                            self.chapter_titles.append(title)
                
                # 更新章节选择器
                self.chapter_combo.clear()
                for title in self.chapter_titles:
                    self.chapter_combo.addItem(title)
                
                # 隐藏缩放控件
                self.zoom_label.setVisible(False)
                self.zoom_out_btn.setVisible(False)
                self.zoom_slider.setVisible(False)
                self.zoom_in_btn.setVisible(False)
                
                # 显示阅读模式控件
                self.read_mode_btn.setVisible(True)
                self.font_size_label.setVisible(True)
                self.font_size_slider.setVisible(True)
                self.chapter_combo.setVisible(True)
                self.progress_label.setVisible(True)
                
                # 设置文本编辑器样式
                self.text_editor.setReadOnly(True)
                self.text_editor.setVisible(True)
                self.image_label.setVisible(False)
                
                # 检查是否有保存的状态
                if file_path in self.file_states:
                    state = self.file_states[file_path]
                    # 恢复字体大小
                    saved_font_size = state.get('font_size', 16)
                    self.font_size = saved_font_size
                    self.font_size_slider.setValue(saved_font_size)
                    
                    # 恢复阅读模式
                    read_mode = state.get('read_mode', True)
                    self.read_mode_btn.setChecked(read_mode)
                    self.toggle_read_mode(read_mode)
                    
                    # 恢复当前章节
                    self.current_chapter = state.get('current_chapter', 0)
                    if 0 <= self.current_chapter < len(self.chapters):
                        self.chapter_combo.setCurrentIndex(self.current_chapter)
                        self.display_chapter()
                
                else:
                    # 默认设置
                    self.current_chapter = 0
                    self.read_mode_btn.setChecked(True)
                    self.toggle_read_mode(True)
                
                # 显示章节内容
                if self.chapters:
                    self.display_chapter()
                else:
                    raise Exception("未找到有效的章节内容")
                
                # 更新阅读进度
                progress = (self.current_chapter + 1) / len(self.chapters) * 100
                self.progress_label.setText(f"进度: {progress:.1f}%")
                
                # 更新状态栏
                self.update_statusbar_for_file_type()
                
            elif file_ext == '.mobi':
                # TODO: 添加MOBI格式支持
                QMessageBox.warning(self, "警告", "暂不支持MOBI格式！")
            
        except Exception as e:
            raise Exception(f"无法加载电子书：{str(e)}")

    def display_chapter(self):
        """显示当前章节"""
        if self.chapters and 0 <= self.current_chapter < len(self.chapters):
            # 设置章节内容
            content = self.chapters[self.current_chapter]
            # 添加段落格式
            formatted_content = content.replace('\n\n', '</p><p>')
            formatted_content = f"""
                <div style='margin: 0 auto; max-width: 800px;'>
                    <h1 style='text-align: center; color: #2C3E50; margin-bottom: 30px;'>
                        {self.chapter_titles[self.current_chapter]}
                    </h1>
                    <p>{formatted_content}</p>
                </div>
            """
            self.text_editor.setHtml(formatted_content)
            
            # 更新状态栏
            title = self.chapter_titles[self.current_chapter]
            self.statusBar.showMessage(f"{title} ({self.current_chapter + 1}/{len(self.chapters)})")
            
            # 更新阅读进度
            progress = (self.current_chapter + 1) / len(self.chapters) * 100
            self.progress_label.setText(f"进度: {progress:.1f}%")

    def chapter_changed(self, index):
        """章节选择改变时的处理"""
        if index != self.current_chapter:
            self.current_chapter = index
            self.display_chapter()

    def toggle_read_mode(self, checked):
        """切换阅读模式"""
        if checked:
            # 进入阅读模式
            self.text_editor.setStyleSheet("""
                QTextEdit {
                    background-color: #F5E6D3;
                    color: #2C3E50;
                    border: none;
                    padding: 20px 40px;
                    selection-background-color: #A9B7C6;
                    selection-color: #2C3E50;
                }
                QScrollBar:vertical {
                    background-color: #F5E6D3;
                    width: 12px;
                    margin: 0px;
                }
                QScrollBar::handle:vertical {
                    background-color: #B4A089;
                    border-radius: 6px;
                    min-height: 20px;
                }
                QScrollBar::handle:vertical:hover {
                    background-color: #8B7355;
                }
                QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical,
                QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
                    background: none;
                    border: none;
                }
            """)
            self.apply_font_settings()
        else:
            # 退出阅读模式
            self.text_editor.setStyleSheet("")
            self.text_editor.setFont(QFont())

    def on_font_size_changed(self, value):
        """处理字体大小变化"""
        self.font_size = value
        self.apply_font_settings()

    def apply_font_settings(self):
        """应用字体设置"""
        font = QFont(self.font_family, self.font_size)
        font.setWeight(QFont.Weight.Normal)
        self.text_editor.setFont(font)
        
        # 设置行高和段落格式
        self.text_editor.document().setDefaultStyleSheet(f"""
            p {{
                line-height: {self.line_height};
                margin-bottom: 1em;
                text-indent: 2em;
                letter-spacing: 0.05em;
            }}
            h1 {{
                font-family: {self.font_family};
                font-size: {self.font_size + 4}pt;
                font-weight: bold;
            }}
        """)

    def create_app_icon(self):
        """创建一个更现代美观的应用图标"""
        # 创建一个 64x64 的图标
        icon_size = 64
        pixmap = QPixmap(icon_size, icon_size)
        pixmap.fill(Qt.GlobalColor.transparent)
        
        # 创建画家
        painter = QPainter(pixmap)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        
        # 绘制主背景 - 使用渐变色
        gradient = QLinearGradient(0, 0, icon_size, icon_size)
        gradient.setColorAt(0, QColor("#1976D2"))  # 深蓝色
        gradient.setColorAt(1, QColor("#2196F3"))  # 蓝色
        painter.setBrush(gradient)
        painter.setPen(Qt.PenStyle.NoPen)
        painter.drawEllipse(2, 2, icon_size-4, icon_size-4)
        
        # 添加轻微的阴影效果
        shadow_color = QColor(0, 0, 0, 40)
        painter.setBrush(shadow_color)
        painter.drawEllipse(4, 5, icon_size-8, icon_size-8)
        
        # 绘制文档主体 - 使用渐变白色
        doc_gradient = QLinearGradient(0, 0, 24, 0)
        doc_gradient.setColorAt(0, QColor("#FFFFFF"))
        doc_gradient.setColorAt(1, QColor("#F5F5F5"))
        painter.setBrush(doc_gradient)
        
        # 创建带有圆角的文档形状
        doc_path = QPainterPath()
        doc_path.addRoundedRect(18, 12, 28, 38, 3, 3)
        painter.drawPath(doc_path)
        
        # 绘制文档折角 - 更平滑美观
        corner_path = QPainterPath()
        corner_path.moveTo(37, 12)
        corner_path.lineTo(46, 12)
        corner_path.lineTo(46, 21)
        corner_path.arcTo(37, 12, 9, 9, 0, 90)
        painter.drawPath(corner_path)
        
        # 反光效果
        highlight = QPainterPath()
        highlight.addRoundedRect(19, 13, 3, 36, 1.5, 1.5)
        painter.setBrush(QColor(255, 255, 255, 40))
        painter.drawPath(highlight)
        
        # 绘制文档线条 - 更美观的间距
        painter.setPen(QColor("#90CAF9"))  # 浅蓝色线条
        painter.drawLine(23, 22, 41, 22)
        painter.drawLine(23, 29, 41, 29)
        painter.drawLine(23, 36, 35, 36)
        painter.drawLine(23, 43, 30, 43)
        
        # 添加一个微妙的高光
        painter.setPen(QPen(QColor(255, 255, 255, 60), 1.5))
        painter.drawArc(5, 5, icon_size-10, icon_size-10, 40*16, 150*16)
        
        painter.end()
        return pixmap

    def setup_context_menu(self):
        """设置右键菜单"""
        # 使用其他程序打开
        open_with_action = QAction("使用其他程序打开(&O)...", self)
        open_with_action.triggered.connect(self.open_with_other_program)
        self.context_menu.addAction(open_with_action)
        
        # 添加分隔线
        self.context_menu.addSeparator()
        
        # 复制文件路径
        copy_path_action = QAction("复制文件路径(&C)", self)
        copy_path_action.triggered.connect(self.copy_file_path)
        self.context_menu.addAction(copy_path_action)
        
        # 在文件资源管理器中显示
        show_in_explorer_action = QAction("在文件资源管理器中显示(&E)", self)
        show_in_explorer_action.triggered.connect(self.show_in_explorer)
        self.context_menu.addAction(show_in_explorer_action)
    
    def contextMenuEvent(self, event):
        """处理右键菜单事件"""
        if self.current_file:
            self.context_menu.exec(event.globalPos())
    
    def open_with_other_program(self):
        """使用其他程序打开文件"""
        if not self.current_file:
            return
            
        try:
            if sys.platform == 'win32':
                os.startfile(self.current_file)
            elif sys.platform == 'darwin':  # macOS
                subprocess.run(['open', '-a', '/System/Applications/Utilities/Terminal.app', self.current_file])
            else:  # Linux
                subprocess.run(['xdg-open', self.current_file])
        except Exception as e:
            QMessageBox.critical(self, "错误", f"无法打开文件：{str(e)}")
    
    def copy_file_path(self):
        """复制文件路径到剪贴板"""
        if self.current_file:
            clipboard = QApplication.clipboard()
            clipboard.setText(self.current_file)
            self.statusBar.showMessage("文件路径已复制到剪贴板", 3000)
    
    def show_in_explorer(self):
        """在文件资源管理器中显示文件"""
        if not self.current_file:
            return
            
        try:
            if sys.platform == 'win32':
                subprocess.run(['explorer', '/select,', self.current_file])
            elif sys.platform == 'darwin':  # macOS
                subprocess.run(['open', '-R', self.current_file])
            else:  # Linux
                subprocess.run(['xdg-open', os.path.dirname(self.current_file)])
        except Exception as e:
            QMessageBox.critical(self, "错误", f"无法打开文件资源管理器：{str(e)}")

    def show_find_dialog(self):
        """显示查找对话框"""
        if not hasattr(self, 'find_dialog'):
            self.find_dialog = QDialog(self)
            self.find_dialog.setWindowTitle("查找")
            self.find_dialog.setFixedSize(350, 150)
            
            layout = QVBoxLayout()
            
            # 添加查找文本框
            search_layout = QHBoxLayout()
            search_label = QLabel("查找内容:")
            self.find_text = QLineEdit()
            self.find_text.returnPressed.connect(self.find_text_in_editor)
            search_layout.addWidget(search_label)
            search_layout.addWidget(self.find_text)
            layout.addLayout(search_layout)
            
            # 添加选项
            options_layout = QHBoxLayout()
            
            # 区分大小写
            self.case_sensitive_checkbox = QCheckBox("区分大小写")
            self.case_sensitive_checkbox.setChecked(True)
            options_layout.addWidget(self.case_sensitive_checkbox)
            
            # 全词匹配
            self.whole_word_checkbox = QCheckBox("全词匹配")
            options_layout.addWidget(self.whole_word_checkbox)
            
            layout.addLayout(options_layout)
            
            # 添加按钮
            btn_layout = QHBoxLayout()
            
            find_prev_btn = QPushButton("查找上一个")
            find_prev_btn.clicked.connect(lambda: self.find_text_in_editor(backward=True))
            
            find_next_btn = QPushButton("查找下一个")
            find_next_btn.clicked.connect(lambda: self.find_text_in_editor(backward=False))
            
            close_btn = QPushButton("关闭")
            close_btn.clicked.connect(self.find_dialog.close)
            
            btn_layout.addWidget(find_prev_btn)
            btn_layout.addWidget(find_next_btn)
            btn_layout.addWidget(close_btn)
            layout.addLayout(btn_layout)
            
            self.find_dialog.setLayout(layout)
        
        self.find_dialog.show()
        # 如果有选中的文本，将其填入查找框
        cursor = self.text_editor.textCursor()
        if cursor.hasSelection():
            self.find_text.setText(cursor.selectedText())
            self.find_text.selectAll()
        
        # 将焦点设置到查找框
        self.find_text.setFocus()

    def find_text_in_editor(self, backward=False):
        """在编辑器中查找文本
        
        Args:
            backward: 是否向后查找
        """
        text = self.find_text.text()
        if not text:
            return
        
        # 获取查找选项
        flags = QTextDocument.FindFlag(0)
        if self.case_sensitive_checkbox.isChecked():
            flags |= QTextDocument.FindFlag.FindCaseSensitively
        if self.whole_word_checkbox.isChecked():
            flags |= QTextDocument.FindFlag.FindWholeWords
        if backward:
            flags |= QTextDocument.FindFlag.FindBackward
        
        # 设置自定义背景色和前景色的文本格式
        search_format = QTextCharFormat()
        search_format.setBackground(QColor(255, 255, 0))  # 黄色背景
        search_format.setForeground(QColor(0, 0, 0))  # 黑色文字
        
        # 从当前位置查找
        cursor = self.text_editor.textCursor()
        
        # 搜索文本
        new_cursor = self.text_editor.document().find(text, cursor, flags)
        
        # 如果找到，选中文本并使用自定义格式
        if not new_cursor.isNull():
            # 选中文本
            self.text_editor.setTextCursor(new_cursor)
            
            # 确保所选文本可见
            self.text_editor.ensureCursorVisible()
            
            # 使用自定义背景色来突出显示找到的文本
            self.highlight_found_text(text)
            
            # 更新光标位置信息
            self.update_cursor_position()
            self.update_selection_info()
        else:
            # 如果没找到，从头/尾开始查找
            if backward:
                start_cursor = QTextCursor(self.text_editor.document())
                start_cursor.movePosition(QTextCursor.MoveOperation.End)
                new_cursor = self.text_editor.document().find(text, start_cursor, flags)
            else:
                start_cursor = QTextCursor(self.text_editor.document())
                start_cursor.movePosition(QTextCursor.MoveOperation.Start)
                new_cursor = self.text_editor.document().find(text, start_cursor, flags)
                
            if not new_cursor.isNull():
                self.text_editor.setTextCursor(new_cursor)
                self.text_editor.ensureCursorVisible()
                self.highlight_found_text(text)
                
                # 更新光标位置信息
                self.update_cursor_position()
                self.update_selection_info()
                
                # 更新状态栏提示从头/尾开始查找
                if backward:
                    self.statusBar.showMessage(f"从文档末尾继续查找 '{text}'")
                else:
                    self.statusBar.showMessage(f"从文档开头继续查找 '{text}'")
            else:
                QMessageBox.information(self, "查找结果", f"找不到 '{text}'")
                self.statusBar.showMessage(f"未找到文本: '{text}'", 3000)

    def highlight_found_text(self, text):
        """突出显示找到的文本"""
        # 获取当前光标
        cursor = self.text_editor.textCursor()
        
        # 清除所有之前的格式
        reset_cursor = QTextCursor(self.text_editor.document())
        reset_cursor.movePosition(QTextCursor.MoveOperation.Start)
        reset_cursor.movePosition(QTextCursor.MoveMode.KeepAnchor)
        reset_format = QTextCharFormat()
        reset_cursor.setCharFormat(reset_format)
        
        # 当前找到的位置应用高亮格式
        highlight_format = QTextCharFormat()
        highlight_format.setBackground(QColor(255, 255, 0))  # 黄色背景
        highlight_format.setForeground(QColor(0, 0, 0))  # 黑色文字
        highlight_format.setFontWeight(QFont.Weight.Bold)  # 粗体
        
        # 应用高亮格式到当前选择
        cursor.mergeCharFormat(highlight_format)
        
        # 更新状态栏
        self.statusBar.showMessage(f"找到文本: '{text}'")

    def show_replace_dialog(self):
        """显示替换对话框"""
        if not hasattr(self, 'replace_dialog'):
            self.replace_dialog = QDialog(self)
            self.replace_dialog.setWindowTitle("替换")
            self.replace_dialog.setFixedSize(350, 200)
            
            layout = QVBoxLayout()
            
            # 添加查找文本框
            search_layout = QHBoxLayout()
            search_label = QLabel("查找内容:")
            self.replace_find_text = QLineEdit()
            search_layout.addWidget(search_label)
            search_layout.addWidget(self.replace_find_text)
            layout.addLayout(search_layout)
            
            # 添加替换文本框
            replace_layout = QHBoxLayout()
            replace_label = QLabel("替换为:")
            self.replace_with_text = QLineEdit()
            replace_layout.addWidget(replace_label)
            replace_layout.addWidget(self.replace_with_text)
            layout.addLayout(replace_layout)
            
            # 添加选项
            options_layout = QHBoxLayout()
            
            # 区分大小写
            self.replace_case_sensitive_checkbox = QCheckBox("区分大小写")
            self.replace_case_sensitive_checkbox.setChecked(True)
            options_layout.addWidget(self.replace_case_sensitive_checkbox)
            
            # 全词匹配
            self.replace_whole_word_checkbox = QCheckBox("全词匹配")
            options_layout.addWidget(self.replace_whole_word_checkbox)
            
            layout.addLayout(options_layout)
            
            # 添加按钮
            btn_layout = QHBoxLayout()
            find_prev_btn = QPushButton("查找上一个")
            find_prev_btn.clicked.connect(lambda: self.find_next_for_replace(backward=True))
            
            find_next_btn = QPushButton("查找下一个")
            find_next_btn.clicked.connect(lambda: self.find_next_for_replace(backward=False))
            
            replace_btn = QPushButton("替换")
            replace_btn.clicked.connect(self.replace_selected)
            
            replace_all_btn = QPushButton("全部替换")
            replace_all_btn.clicked.connect(self.replace_all)
            
            close_btn = QPushButton("关闭")
            close_btn.clicked.connect(self.replace_dialog.close)
            
            btn_layout.addWidget(find_prev_btn)
            btn_layout.addWidget(find_next_btn)
            btn_layout.addWidget(replace_btn)
            btn_layout.addWidget(replace_all_btn)
            btn_layout.addWidget(close_btn)
            layout.addLayout(btn_layout)
            
            self.replace_dialog.setLayout(layout)
        
        self.replace_dialog.show()
        
        # 如果有选中的文本，将其填入查找框
        cursor = self.text_editor.textCursor()
        if cursor.hasSelection():
            self.replace_find_text.setText(cursor.selectedText())
            self.replace_find_text.selectAll()
        
        # 将焦点设置到查找框
        self.replace_find_text.setFocus()

    def find_next_for_replace(self, backward=False):
        """为替换功能查找下一个匹配项
        
        Args:
            backward: 是否向后查找
        """
        text = self.replace_find_text.text()
        if not text:
            return
        
        # 获取查找选项
        flags = QTextDocument.FindFlag(0)
        if self.replace_case_sensitive_checkbox.isChecked():
            flags |= QTextDocument.FindFlag.FindCaseSensitively
        if self.replace_whole_word_checkbox.isChecked():
            flags |= QTextDocument.FindFlag.FindWholeWords
        if backward:
            flags |= QTextDocument.FindFlag.FindBackward
        
        # 从当前位置查找
        cursor = self.text_editor.textCursor()
        
        # 搜索文本
        new_cursor = self.text_editor.document().find(text, cursor, flags)
        
        # 如果找到，选中文本
        if not new_cursor.isNull():
            self.text_editor.setTextCursor(new_cursor)
            self.text_editor.ensureCursorVisible()
            
            # 使用自定义背景色来突出显示找到的文本
            self.highlight_found_text(text)
            
            # 更新光标位置信息
            self.update_cursor_position()
            self.update_selection_info()
        else:
            # 如果没找到，从头/尾开始查找
            if backward:
                start_cursor = QTextCursor(self.text_editor.document())
                start_cursor.movePosition(QTextCursor.MoveOperation.End)
                new_cursor = self.text_editor.document().find(text, start_cursor, flags)
            else:
                start_cursor = QTextCursor(self.text_editor.document())
                start_cursor.movePosition(QTextCursor.MoveOperation.Start)
                new_cursor = self.text_editor.document().find(text, start_cursor, flags)
                
            if not new_cursor.isNull():
                self.text_editor.setTextCursor(new_cursor)
                self.text_editor.ensureCursorVisible()
                self.highlight_found_text(text)
                
                # 更新光标位置信息
                self.update_cursor_position()
                self.update_selection_info()
                
                # 更新状态栏提示从头/尾开始查找
                if backward:
                    self.statusBar.showMessage(f"从文档末尾继续查找 '{text}'")
                else:
                    self.statusBar.showMessage(f"从文档开头继续查找 '{text}'")
            else:
                QMessageBox.information(self, "查找结果", f"找不到 '{text}'")
                self.statusBar.showMessage(f"未找到文本: '{text}'", 3000)

    def replace_selected(self):
        """替换当前选中的文本"""
        cursor = self.text_editor.textCursor()
        if cursor.hasSelection():
            selected_text = cursor.selectedText()
            replace_text = self.replace_with_text.text()
            cursor.insertText(replace_text)
            self.statusBar.showMessage(f"已替换: '{selected_text}' -> '{replace_text}'")
            
            # 更新文本信息
            if self.current_file:
                self.update_text_file_info(self.current_file)
        
        self.find_next_for_replace()

    def replace_all(self):
        """替换所有匹配的文本"""
        find_text = self.replace_find_text.text()
        replace_text = self.replace_with_text.text()
        
        if not find_text:
            return
        
        # 获取查找选项
        flags = QTextDocument.FindFlag(0)
        if self.replace_case_sensitive_checkbox.isChecked():
            flags |= QTextDocument.FindFlag.FindCaseSensitively
        if self.replace_whole_word_checkbox.isChecked():
            flags |= QTextDocument.FindFlag.FindWholeWords
        
        count = 0
        # 开始文档修改
        cursor = self.text_editor.textCursor()
        cursor.movePosition(QTextCursor.MoveOperation.Start)
        self.text_editor.setTextCursor(cursor)
        
        # 循环替换所有匹配项
        while True:
            # 获取当前光标位置
            current_pos = cursor.position()
            
            # 搜索文本
            new_cursor = self.text_editor.document().find(find_text, cursor, flags)
            
            # 如果找到，替换文本
            if not new_cursor.isNull():
                self.text_editor.setTextCursor(new_cursor)
                cursor = self.text_editor.textCursor()
                cursor.insertText(replace_text)
                count += 1
                # 更新光标位置为替换后的位置
                self.text_editor.setTextCursor(cursor)
                cursor = self.text_editor.textCursor()
            else:
                break
        
        # 更新文本信息
        if self.current_file:
            self.update_text_file_info(self.current_file)
        
        # 更新状态栏信息
        self.statusBar.showMessage(f"已替换 {count} 处 '{find_text}' -> '{replace_text}'")
        
        QMessageBox.information(self, "替换完成", f"共替换了 {count} 处")

    def toggle_statusbar(self):
        """切换状态栏显示/隐藏"""
        if self.statusBar.isVisible():
            self.statusBar.hide()
            self.toggle_statusbar_action.setText("显示状态栏")
        else:
            self.statusBar.show()
            self.toggle_statusbar_action.setText("隐藏状态栏")

    def toggle_control_panel(self):
        """切换功能栏显示/隐藏"""
        if self.control_panel.isVisible():
            self.control_panel.hide()
            self.toggle_control_panel_action.setText("显示功能栏")
        else:
            self.control_panel.show()
            self.toggle_control_panel_action.setText("隐藏功能栏")

    def render_markdown(self, content):
        """将Markdown内容转换为格式化的HTML
        
        Args:
            content: Markdown格式的文本内容
            
        Returns:
            格式化后的HTML内容
        """
        # 转换Markdown为HTML
        html_content = markdown.markdown(
            content,
            extensions=['markdown.extensions.fenced_code', 
                      'markdown.extensions.tables',
                      'markdown.extensions.toc',
                      'markdown.extensions.extra'],
            output_format='html5'
        )
        
        # 添加样式
        styled_html = f"""
        <html>
        <head>
            <style>
                body {{
                    font-family: 'Segoe UI', Arial, sans-serif;
                    line-height: 1.6;
                    padding: 20px;
                    color: #333;
                    background-color: #f9f9f9;
                }}
                h1, h2, h3, h4, h5, h6 {{
                    color: #2c3e50;
                    font-weight: 600;
                    margin-top: 20px;
                    margin-bottom: 10px;
                }}
                h1 {{ font-size: 28px; border-bottom: 1px solid #ddd; padding-bottom: 10px; }}
                h2 {{ font-size: 24px; }}
                h3 {{ font-size: 20px; }}
                a {{ color: #3498db; text-decoration: none; }}
                a:hover {{ text-decoration: underline; }}
                pre, code {{
                    background-color: #f0f0f0;
                    border-radius: 3px;
                    font-family: Consolas, Monaco, 'Andale Mono', monospace;
                    padding: 0.2em 0.4em;
                    overflow-x: auto;
                }}
                pre {{ padding: 15px; margin: 15px 0; }}
                blockquote {{
                    border-left: 5px solid #ddd;
                    padding-left: 15px;
                    color: #777;
                    margin: 15px 0;
                }}
                hr {{ border: 0; border-top: 1px solid #ddd; margin: 20px 0; }}
                table {{
                    border-collapse: collapse;
                    width: 100%;
                    margin: 15px 0;
                }}
                th, td {{
                    padding: 8px;
                    border: 1px solid #ddd;
                    text-align: left;
                }}
                th {{ background-color: #f2f2f2; }}
                img {{ max-width: 100%; }}
                ul, ol {{ padding-left: 25px; }}
            </style>
        </head>
        <body>
            {html_content}
        </body>
        </html>
        """
        
        return styled_html

    def on_markdown_text_changed(self):
        """Markdown文本改变时实时更新预览"""
        if self.markdown_preview_mode:
            content = self.markdown_editor.toPlainText()
            if content.strip():
                styled_html = self.render_markdown(content)
                self.markdown_preview.setHtml(styled_html)
            else:
                self.markdown_preview.setHtml("<p>在左侧编辑器中输入Markdown内容以查看预览...</p>")
            
            # 标记文件已修改
            self.text_changed = True
            if self.current_file:
                self.setWindowTitle(f"GoFile - {os.path.basename(self.current_file)} *")

    def toggle_markdown_preview_mode(self):
        """切换Markdown分屏预览模式"""
        if not self.current_file:
            return
            
        file_ext = os.path.splitext(self.current_file)[1].lower()
        if file_ext not in ['.md', '.markdown', '.mdown', '.mdwn', '.mkd', '.mkdn']:
            QMessageBox.warning(self, "警告", "只有Markdown文件才能使用分屏预览模式！")
            return
            
        self.markdown_preview_mode = not self.markdown_preview_mode
        
        if self.markdown_preview_mode:
            # 切换到分屏预览模式
            self.text_editor.setVisible(False)
            self.markdown_splitter.setVisible(True)
            
            # 读取当前文件内容到编辑器
            try:
                with open(self.current_file, 'r', encoding='utf-8') as file:
                    content = file.read()
                    self.markdown_editor.setText(content)
                    # 立即更新预览
                    styled_html = self.render_markdown(content)
                    self.markdown_preview.setHtml(styled_html)
            except Exception as e:
                QMessageBox.critical(self, "错误", f"无法读取文件：{str(e)}")
                return
                
            # 更新按钮状态
            self.edit_btn.setText("退出预览")
            self.edit_btn.setChecked(True)
            self.save_btn.setVisible(True)
            
        else:
            # 退出分屏预览模式
            self.markdown_splitter.setVisible(False)
            self.text_editor.setVisible(True)
            
            # 重新加载文件到普通文本编辑器
            self.load_file(self.current_file)
            
            # 更新按钮状态
            self.edit_btn.setText("编辑模式")
            self.edit_btn.setChecked(False)
            self.save_btn.setVisible(False)
            self.text_changed = False
            
        # 更新菜单项状态
        self.toggle_markdown_preview_action.setChecked(self.markdown_preview_mode)
        
        # 更新窗口标题
        if self.current_file:
            title = f"GoFile - {os.path.basename(self.current_file)}"
            if self.markdown_preview_mode and self.text_changed:
                title += " *"
            self.setWindowTitle(title)

    def dragEnterEvent(self, event):
        """处理拖拽进入事件"""
        # 检查是否包含文件URL
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
            # 显示拖放提示
            self.statusBar.showMessage("释放鼠标以打开文件")
    
    def dragLeaveEvent(self, event):
        """处理拖拽离开事件"""
        # 清除状态栏提示
        self.statusBar.showMessage("就绪")
        event.accept()
    
    def dragMoveEvent(self, event):
        """处理拖拽移动事件"""
        # 如果有URL，接受拖放动作
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
    
    def dropEvent(self, event):
        """处理拖放事件"""
        # 获取被拖放的文件URL
        urls = event.mimeData().urls()
        
        if urls:
            # 只处理第一个文件（如果有多个）
            file_path = urls[0].toLocalFile()
            
            # 检查文件是否存在
            if not os.path.exists(file_path):
                QMessageBox.warning(self, "错误", f"文件不存在: {file_path}")
                return
            
            # 检查当前窗口是否已经打开文件
            if self.current_file:
                # 已有打开的文件，创建新窗口
                try:
                    # 创建新窗口并加载文件
                    new_window = MainWindow()
                    new_window.show()
                    new_window.load_file(file_path)
                    
                    # 刷新所有窗口的窗口菜单
                    global all_windows
                    for window in all_windows:
                        if window.isVisible():
                            try:
                                window.refresh_window_menu()
                            except:
                                pass
                    
                    # 更新状态栏
                    new_window.statusBar.showMessage(f"已在新窗口中通过拖放打开: {file_path}")
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"无法在新窗口中打开文件：{str(e)}")
            else:
                # 如果有未保存的更改，提示保存
                if hasattr(self, 'text_changed') and self.text_changed:
                    reply = QMessageBox.question(
                        self,
                        "保存更改",
                        "当前文件有未保存的更改，是否保存？",
                        QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel
                    )
                    
                    if reply == QMessageBox.StandardButton.Save:
                        if not self.save_file():
                            # 如果保存失败，取消打开新文件
                            return
                    elif reply == QMessageBox.StandardButton.Cancel:
                        # 用户取消，不打开新文件
                        return
                
                # 在当前窗口中打开文件
                self.load_file(file_path)
                
                # 更新状态栏
                self.statusBar.showMessage(f"已通过拖放打开: {file_path}")
            
        event.acceptProposedAction()

    def load_office_file(self, file_path):
        """加载Office文档文件
        
        支持的格式：
        - .docx (Word文档)
        - .xlsx (Excel表格)
        - .pptx (PowerPoint演示文稿)
        - .odt (OpenDocument文本文档)
        - .ods (OpenDocument电子表格)
        - .odp (OpenDocument演示文稿)
        
        Args:
            file_path: 文件路径
        """
        try:
            # 获取文件扩展名
            file_ext = os.path.splitext(file_path)[1].lower()
            
            # 清除之前的内容
            self.text_editor.clear()
            self.text_editor.setVisible(True)
            self.image_label.setVisible(False)
            
            # 设置只读模式
            self.text_editor.setReadOnly(True)
            self.edit_btn.setVisible(False)
            
            # 隐藏不需要的控件
            if hasattr(self, 'thumbnails_splitter'):
                self.thumbnails_splitter.setVisible(False)
            
            if hasattr(self, 'page_selector'):
                self.page_selector.setVisible(False)
            
            html_content = ""
            
            # 根据文件类型处理
            if file_ext == '.docx':
                html_content = self.convert_docx_to_html(file_path)
                self.statusBar.showMessage(f"Word文档: {os.path.basename(file_path)}")
            elif file_ext == '.xlsx':
                html_content = self.convert_xlsx_to_html(file_path)
                self.statusBar.showMessage(f"Excel表格: {os.path.basename(file_path)}")
            elif file_ext == '.pptx':
                html_content = self.convert_pptx_to_html(file_path)
                self.statusBar.showMessage(f"PowerPoint演示文稿: {os.path.basename(file_path)}")
            elif file_ext in ['.odt', '.ods', '.odp']:
                # 暂不支持OpenDocument格式，提示用户
                html_content = f"""
                <html>
                <body style="font-family: Arial, sans-serif; padding: 20px;">
                    <h2>OpenDocument 格式</h2>
                    <p>当前暂不支持直接查看 {file_ext} 格式文件的内容。</p>
                    <p>请考虑将其转换为 .docx、.xlsx 或 .pptx 格式后查看。</p>
                </body>
                </html>
                """
                self.statusBar.showMessage(f"OpenDocument文件: {os.path.basename(file_path)}")
            
            # 设置HTML内容
            self.text_editor.setHtml(html_content)
            
            # 更新当前文件类型状态
            self.update_statusbar_for_file_type()
            self.file_type_label.setText(f"Office文档 | {file_ext[1:].upper()}")
            
            # 获取文件大小
            file_size = os.path.getsize(file_path)
            size_str = self.format_file_size(file_size)
            
            # 更新文件信息
            self.file_info_label.setText(f"文件大小: {size_str}")
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"无法加载Office文档：{str(e)}")
    
    def convert_docx_to_html(self, file_path):
        """将Word文档转换为HTML格式
        
        Args:
            file_path: Word文档路径
            
        Returns:
            str: HTML内容
        """
        try:
            # 打开Word文档
            doc = docx.Document(file_path)
            
            # 用于存储HTML内容
            html_parts = []
            html_parts.append("""
            <html>
            <head>
                <style>
                    body {
                        font-family: 'Segoe UI', Arial, sans-serif;
                        line-height: 1.5;
                        padding: 20px;
                        max-width: 800px;
                        margin: 0 auto;
                    }
                    h1, h2, h3, h4, h5, h6 {
                        color: #1e88e5;
                        margin-top: 1.2em;
                        margin-bottom: 0.5em;
                    }
                    p {
                        margin: 0.8em 0;
                    }
                    table {
                        border-collapse: collapse;
                        width: 100%;
                        margin: 1em 0;
                    }
                    th, td {
                        border: 1px solid #ddd;
                        padding: 8px;
                        text-align: left;
                    }
                    th {
                        background-color: #f2f2f2;
                    }
                    .page-break {
                        page-break-after: always;
                        border-bottom: 1px dashed #ccc;
                        margin: 2em 0;
                    }
                </style>
            </head>
            <body>
            """)
            
            # 处理文档标题
            html_parts.append(f"<h1>{os.path.basename(file_path)}</h1>")
            html_parts.append("<hr>")
            
            # 处理段落和表格
            for element in doc.element.body:
                if element.tag.endswith('p'):  # 段落
                    paragraph = docx.Document().add_paragraph()
                    paragraph._element = element
                    paragraph._parent = doc
                    text = paragraph.text
                    
                    # 如果是标题，使用适当的标签
                    if hasattr(paragraph, 'style') and paragraph.style and 'Heading' in paragraph.style.name:
                        heading_level = int(paragraph.style.name[-1]) if paragraph.style.name[-1].isdigit() else 1
                        heading_level = min(heading_level, 6)  # 最大h6
                        html_parts.append(f"<h{heading_level}>{escape(text)}</h{heading_level}>")
                    else:
                        html_parts.append(f"<p>{escape(text)}</p>")
                
                elif element.tag.endswith('tbl'):  # 表格
                    html_parts.append("<table>")
                    
                    # 处理表格行
                    for row in element.findall('.//{*}tr'):
                        html_parts.append("<tr>")
                        
                        # 处理单元格
                        for cell in row.findall('.//{*}tc'):
                            # 获取单元格文本
                            paragraphs = cell.findall('.//{*}p')
                            cell_text = ' '.join([p.text for p in paragraphs if hasattr(p, 'text')])
                            
                            # 添加单元格
                            html_parts.append(f"<td>{escape(cell_text)}</td>")
                        
                        html_parts.append("</tr>")
                    
                    html_parts.append("</table>")
                
                elif element.tag.endswith('sectPr'):  # 分节符，可能是分页符
                    html_parts.append('<div class="page-break"></div>')
            
            html_parts.append("</body></html>")
            return "".join(html_parts)
            
        except Exception as e:
            return f"""
            <html>
            <body style="font-family: Arial, sans-serif; padding: 20px;">
                <h2>无法解析Word文档</h2>
                <p>解析文档时发生错误：{str(e)}</p>
                <p>可能是文档格式不兼容或文档已损坏。</p>
            </body>
            </html>
            """
    
    def convert_xlsx_to_html(self, file_path):
        """将Excel表格转换为HTML格式
        
        Args:
            file_path: Excel文件路径
            
        Returns:
            str: HTML内容
        """
        try:
            # 打开Excel文件
            workbook = openpyxl.load_workbook(file_path, data_only=True)
            
            # 用于存储HTML内容
            html_parts = []
            html_parts.append("""
            <html>
            <head>
                <style>
                    body {
                        font-family: 'Segoe UI', Arial, sans-serif;
                        padding: 10px;
                    }
                    h1, h2 {
                        color: #1e88e5;
                    }
                    .sheet-title {
                        font-size: 1.2em;
                        margin: 1.5em 0 0.5em 0;
                        padding: 5px 10px;
                        background-color: #f0f7ff;
                        border-left: 4px solid #1e88e5;
                        cursor: pointer;
                    }
                    .sheet-content {
                        margin-bottom: 20px;
                        overflow-x: auto;
                    }
                    table {
                        border-collapse: collapse;
                        width: 100%;
                        min-width: 600px;
                    }
                    th, td {
                        border: 1px solid #ddd;
                        padding: 6px;
                        text-align: left;
                    }
                    th {
                        background-color: #f2f2f2;
                        position: sticky;
                        top: 0;
                    }
                    tr:nth-child(even) {
                        background-color: #f9f9f9;
                    }
                    .hidden {
                        display: none;
                    }
                </style>
                <script>
                    function toggleSheet(sheetId) {
                        var content = document.getElementById(sheetId);
                        if (content.classList.contains('hidden')) {
                            content.classList.remove('hidden');
                        } else {
                            content.classList.add('hidden');
                        }
                    }
                </script>
            </head>
            <body>
            """)
            
            # 添加文件标题
            html_parts.append(f"<h1>{os.path.basename(file_path)}</h1>")
            html_parts.append(f"<p>工作表数量: {len(workbook.sheetnames)}</p>")
            html_parts.append("<hr>")
            
            # 处理每个工作表
            for sheet_index, sheet_name in enumerate(workbook.sheetnames):
                sheet = workbook[sheet_name]
                
                # 工作表标题，可点击展开/折叠
                html_parts.append(f'<div class="sheet-title" onclick="toggleSheet(\'sheet{sheet_index}\')">{escape(sheet_name)}</div>')
                
                # 工作表内容区域，默认显示第一个工作表，其他折叠
                is_hidden = ' hidden' if sheet_index > 0 else ''
                html_parts.append(f'<div id="sheet{sheet_index}" class="sheet-content{is_hidden}">')
                
                # 创建表格
                html_parts.append('<table>')
                
                # 获取使用的单元格范围
                min_row = 1
                min_col = 1
                max_row = max(sheet.max_row, 1)
                max_col = max(sheet.max_column, 1)
                
                # 限制处理范围，避免过大表格
                max_row = min(max_row, 1000)  # 最多显示1000行
                max_col = min(max_col, 50)    # 最多显示50列
                
                # 添加列标题 (A, B, C...)
                html_parts.append('<tr><th></th>')
                for col in range(min_col, max_col + 1):
                    col_letter = openpyxl.utils.get_column_letter(col)
                    html_parts.append(f'<th>{col_letter}</th>')
                html_parts.append('</tr>')
                
                # 添加数据行
                for row in range(min_row, max_row + 1):
                    html_parts.append(f'<tr><th>{row}</th>')
                    
                    for col in range(min_col, max_col + 1):
                        cell = sheet.cell(row=row, column=col)
                        value = cell.value if cell.value is not None else ""
                        
                        # 处理不同的数据类型
                        if isinstance(value, datetime):
                            value = value.strftime('%Y-%m-%d %H:%M:%S')
                        
                        html_parts.append(f'<td>{escape(str(value))}</td>')
                    
                    html_parts.append('</tr>')
                
                html_parts.append('</table>')
                
                # 当表格过大时添加提示
                if sheet.max_row > 1000 or sheet.max_column > 50:
                    html_parts.append('<p style="color: #888; font-style: italic;">注意：此表格过大，仅显示部分内容。</p>')
                
                html_parts.append('</div>')
            
            html_parts.append("</body></html>")
            return "".join(html_parts)
            
        except Exception as e:
            return f"""
            <html>
            <body style="font-family: Arial, sans-serif; padding: 20px;">
                <h2>无法解析Excel表格</h2>
                <p>解析表格时发生错误：{str(e)}</p>
                <p>可能是表格格式不兼容或文件已损坏。</p>
            </body>
            </html>
            """
    
    def convert_pptx_to_html(self, file_path):
        """将PowerPoint演示文稿转换为HTML格式
        
        Args:
            file_path: PowerPoint文件路径
            
        Returns:
            str: HTML内容
        """
        try:
            # 打开PowerPoint文件
            presentation = Presentation(file_path)
            
            # 用于存储HTML内容
            html_parts = []
            html_parts.append("""
            <html>
            <head>
                <style>
                    body {
                        font-family: 'Segoe UI', Arial, sans-serif;
                        padding: 20px;
                        max-width: 900px;
                        margin: 0 auto;
                    }
                    h1, h2 {
                        color: #1e88e5;
                    }
                    .slide {
                        border: 1px solid #ddd;
                        padding: 20px;
                        margin-bottom: 30px;
                        border-radius: 5px;
                        box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                        background-color: white;
                    }
                    .slide-title {
                        font-size: 1.4em;
                        margin-top: 0;
                        padding-bottom: 10px;
                        border-bottom: 1px solid #eee;
                        color: #333;
                    }
                    .slide-number {
                        float: right;
                        font-size: 0.8em;
                        color: #888;
                        margin-top: 5px;
                    }
                    .slide-content {
                        margin-top: 15px;
                    }
                    ul {
                        margin-top: 10px;
                        margin-bottom: 10px;
                    }
                    li {
                        margin-bottom: 5px;
                    }
                </style>
            </head>
            <body>
            """)
            
            # 添加文件标题
            html_parts.append(f"<h1>{os.path.basename(file_path)}</h1>")
            html_parts.append(f"<p>幻灯片数量: {len(presentation.slides)}</p>")
            html_parts.append("<hr>")
            
            # 处理每张幻灯片
            for i, slide in enumerate(presentation.slides):
                slide_num = i + 1
                html_parts.append(f'<div class="slide">')
                html_parts.append(f'<div class="slide-number">幻灯片 {slide_num}/{len(presentation.slides)}</div>')
                
                # 获取幻灯片标题
                title = "无标题"
                for shape in slide.shapes:
                    if hasattr(shape, "has_text_frame") and shape.has_text_frame:
                        if shape.text.strip():
                            title = shape.text.strip()
                            break
                
                html_parts.append(f'<h2 class="slide-title">{escape(title)}</h2>')
                html_parts.append('<div class="slide-content">')
                
                # 提取幻灯片内容
                for shape in slide.shapes:
                    if hasattr(shape, "has_text_frame") and shape.has_text_frame:
                        if shape.text.strip() and shape.text.strip() != title:
                            text = shape.text.strip()
                            
                            # 分析是否是列表项
                            if text.startswith('•') or text.startswith('-') or text.startswith('*'):
                                # 分割列表项
                                list_items = [item.strip() for item in re.split(r'[•\-*]\s+', text) if item.strip()]
                                if list_items:
                                    html_parts.append('<ul>')
                                    for item in list_items:
                                        html_parts.append(f'<li>{escape(item)}</li>')
                                    html_parts.append('</ul>')
                            else:
                                html_parts.append(f'<p>{escape(text)}</p>')
                
                html_parts.append('</div>')
                html_parts.append('</div>')
            
            html_parts.append("</body></html>")
            return "".join(html_parts)
            
        except Exception as e:
            return f"""
            <html>
            <body style="font-family: Arial, sans-serif; padding: 20px;">
                <h2>无法解析PowerPoint演示文稿</h2>
                <p>解析演示文稿时发生错误：{str(e)}</p>
                <p>可能是演示文稿格式不兼容或文件已损坏。</p>
            </body>
            </html>
            """

    def format_file_size(self, size_in_bytes):
        """格式化文件大小为人类可读格式
        
        Args:
            size_in_bytes: 文件大小（字节）
            
        Returns:
            str: 格式化后的文件大小
        """
        if size_in_bytes < 1024:
            return f"{size_in_bytes} B"
        elif size_in_bytes < 1024 * 1024:
            return f"{size_in_bytes / 1024:.1f} KB"
        elif size_in_bytes < 1024 * 1024 * 1024:
            return f"{size_in_bytes / (1024 * 1024):.1f} MB"
        else:
            return f"{size_in_bytes / (1024 * 1024 * 1024):.1f} GB"

    def create_new_window(self):
        """创建一个新的应用程序窗口"""
        try:
            # 创建新窗口
            new_window = MainWindow()
            new_window.show()
            
            # 保存窗口引用（防止被垃圾回收）
            global all_windows
            all_windows.append(new_window)
            
            # 刷新所有窗口的窗口菜单
            for window in all_windows:
                if window.isVisible():
                    try:
                        window.refresh_window_menu()
                    except Exception as e:
                        print(f"刷新窗口菜单错误: {str(e)}")
                
            # 显示状态栏消息
            self.statusBar.showMessage("已创建新窗口", 3000)
            
            return new_window
        except Exception as e:
            QMessageBox.critical(self, "错误", f"创建新窗口失败: {str(e)}")
            return None
    
    def refresh_window_menu(self):
        """刷新窗口菜单中的窗口列表"""
        try:
            # 确保窗口菜单存在
            if not hasattr(self, 'window_menu'):
                return
                
            # 清除旧的窗口操作
            for action in self.window_menu.actions():
                if hasattr(action, 'window_id'):
                    self.window_menu.removeAction(action)
            
            # 添加所有窗口到菜单
            global all_windows
            valid_windows = []
            
            # 过滤出有效窗口并添加到菜单
            for i, window in enumerate(all_windows):
                if window and window.isVisible():
                    valid_windows.append(window)
                    
                    # 创建窗口标题（显示当前加载的文件）
                    window_title = f"{i+1}: "
                    if hasattr(window, 'current_file') and window.current_file:
                        window_title += os.path.basename(window.current_file)
                    else:
                        window_title += "未命名"
                    
                    # 如果当前窗口，添加标记
                    if window == self:
                        window_title += " [当前]"
                    
                    # 创建操作并添加到菜单
                    action = QAction(window_title, self)
                    action.window_id = i
                    action.triggered.connect(lambda checked, idx=i: self.switch_to_window(idx))
                    self.window_menu.addAction(action)
            
            # 更新全局窗口列表（只保留有效窗口）
            all_windows = valid_windows
        except Exception as e:
            print(f"刷新窗口菜单错误: {str(e)}")
    
    def switch_to_window(self, window_index):
        """切换到指定索引的窗口"""
        try:
            global all_windows
            if 0 <= window_index < len(all_windows):
                window = all_windows[window_index]
                if window and window.isVisible():
                    window.setWindowState(window.windowState() & ~Qt.WindowState.WindowMinimized | Qt.WindowState.WindowActive)
                    window.activateWindow()
                    window.raise_()
        except Exception as e:
            print(f"切换窗口错误: {str(e)}")

    def load_audio_file(self, file_path):
        """加载音乐文件"""
        try:
            # 设置音频源
            self.media_player.setSource(QUrl.fromLocalFile(file_path))
            
            # 隐藏视频相关控件
            self.video_widget.setVisible(False)
            self.text_editor.setVisible(False)
            
            # 默认显示中央动态歌词而不是音乐封面
            self.image_label.setVisible(False)
            
            # 显示音乐播放器控件
            self.play_btn.setVisible(True)
            self.video_slider.setVisible(True)
            
            # 隐藏缩放控件
            self.zoom_label.setVisible(False)
            self.zoom_out_btn.setVisible(False)
            self.zoom_slider.setVisible(False)
            self.zoom_in_btn.setVisible(False)
            
            # 创建音乐封面（用于备用显示）
            self.display_audio_cover(file_path)
            
            # 先加载歌词数据
            if hasattr(self, 'lyrics_dict'):
                self.current_lyrics = self.get_lyrics_for_music(file_path)
            
            # 显示中央动态歌词
            self.display_center_lyrics(True)
            
            # 创建音量控制
            if not hasattr(self, 'volume_label'):
                self.volume_label = QLabel("音量")
                self.volume_label.setFixedWidth(50)
                self.volume_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                # 将音量标签插入到播放按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.play_btn) + 1, self.volume_label)
            
            if not hasattr(self, 'volume_slider'):
                self.volume_slider = QSlider(Qt.Orientation.Horizontal)
                self.volume_slider.setMinimum(0)
                self.volume_slider.setMaximum(100)
                self.volume_slider.setValue(50)  # 默认音量50%
                self.volume_slider.setFixedWidth(100)
                self.volume_slider.valueChanged.connect(self.on_volume_changed)
                # 将音量滑动条插入到音量标签后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.volume_label) + 1, self.volume_slider)
            
            # 显示音量控制
            self.volume_label.setVisible(True)
            self.volume_slider.setVisible(True)
            
            # 添加音乐时间显示标签
            if not hasattr(self, 'audio_time_label'):
                self.audio_time_label = QLabel("00:00 / 00:00")
                self.audio_time_label.setFixedWidth(120)
                self.audio_time_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                self.control_layout.insertWidget(self.control_layout.indexOf(self.video_slider) + 1, self.audio_time_label)
            
            self.audio_time_label.setVisible(True)
            
            # 添加播放列表控制按钮
            if not hasattr(self, 'prev_btn'):
                self.prev_btn = QPushButton("上一曲")
                self.prev_btn.setFixedWidth(60)
                self.prev_btn.clicked.connect(self.play_previous)
                # 将上一曲按钮插入到播放按钮前面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.play_btn), self.prev_btn)
            
            if not hasattr(self, 'next_btn'):
                self.next_btn = QPushButton("下一曲")
                self.next_btn.setFixedWidth(60)
                self.next_btn.clicked.connect(self.play_next)
                # 将下一曲按钮插入到音量滑动条后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.volume_slider) + 1, self.next_btn)
            
            if not hasattr(self, 'play_mode_btn'):
                self.play_mode_btn = QPushButton("顺序播放")
                self.play_mode_btn.setFixedWidth(80)
                self.play_mode_btn.clicked.connect(self.toggle_play_mode)
                # 将播放模式按钮插入到下一曲按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.next_btn) + 1, self.play_mode_btn)
            
            if not hasattr(self, 'playlist_btn'):
                self.playlist_btn = QPushButton("播放列表")
                self.playlist_btn.setFixedWidth(80)
                self.playlist_btn.clicked.connect(self.toggle_playlist_panel)
                # 将播放列表按钮插入到播放模式按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.play_mode_btn) + 1, self.playlist_btn)
            
            # 添加歌词按钮
            if not hasattr(self, 'lyrics_btn'):
                self.lyrics_btn = QPushButton("歌词")
                self.lyrics_btn.setFixedWidth(50)
                self.lyrics_btn.clicked.connect(self.toggle_lyrics_panel)
                # 将歌词按钮插入到播放列表按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.playlist_btn) + 1, self.lyrics_btn)
            
            # 添加切换封面/歌词显示按钮
            if not hasattr(self, 'toggle_cover_btn'):
                self.toggle_cover_btn = QPushButton("设置封面")
                self.toggle_cover_btn.setFixedWidth(80)
                self.toggle_cover_btn.setCheckable(False)  # 不再是切换按钮
                self.toggle_cover_btn.clicked.connect(self.set_audio_cover)
                # 将切换按钮插入到歌词按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.lyrics_btn) + 1, self.toggle_cover_btn)
            
            # 添加桌面歌词按钮
            if not hasattr(self, 'desktop_lyric_btn'):
                self.desktop_lyric_btn = QPushButton("桌面歌词")
                self.desktop_lyric_btn.setFixedWidth(80)
                self.desktop_lyric_btn.setCheckable(True)
                self.desktop_lyric_btn.setChecked(False)  # 默认不显示桌面歌词
                self.desktop_lyric_btn.clicked.connect(self.toggle_desktop_lyrics)
                # 将桌面歌词按钮插入到切换封面按钮后面
                self.control_layout.insertWidget(self.control_layout.indexOf(self.toggle_cover_btn) + 1, self.desktop_lyric_btn)
            
            # 显示控制按钮
            self.prev_btn.setVisible(True)
            self.next_btn.setVisible(True)
            self.play_mode_btn.setVisible(True)
            self.playlist_btn.setVisible(True)
            self.lyrics_btn.setVisible(True)
            self.toggle_cover_btn.setVisible(True)
            self.desktop_lyric_btn.setVisible(True)
            
            # 创建播放列表面板（如果不存在）
            if not hasattr(self, 'playlist_panel'):
                # 创建播放列表面板
                self.playlist_panel = QWidget()
                # self.playlist_panel.setMinimumWidth(250)
                # self.playlist_panel.setMaximumWidth(300)
                self.playlist_panel.setVisible(False)  # 默认隐藏
                
                # 创建播放列表布局
                playlist_layout = QVBoxLayout(self.playlist_panel)
                
                # 创建播放列表标题
                playlist_title = QLabel("播放列表")
                playlist_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
                playlist_title.setStyleSheet("font-weight: bold; font-size: 14px;")
                playlist_layout.addWidget(playlist_title)
                
                # 创建播放列表控制按钮布局
                playlist_btn_layout = QHBoxLayout()
                
                # 添加播放列表文件按钮
                self.add_music_btn = QPushButton("添加音乐")
                self.add_music_btn.clicked.connect(self.add_to_playlist)
                playlist_btn_layout.addWidget(self.add_music_btn)
                
                # 添加清空播放列表按钮
                self.clear_playlist_btn = QPushButton("清空列表")
                self.clear_playlist_btn.clicked.connect(self.clear_playlist)
                playlist_btn_layout.addWidget(self.clear_playlist_btn)
                
                playlist_layout.addLayout(playlist_btn_layout)
                
                # 创建播放列表视图
                self.playlist_view = QListWidget()
                self.playlist_view.itemDoubleClicked.connect(self.playlist_item_double_clicked)
                self.playlist_view.setAlternatingRowColors(True)
                # 设置右键菜单支持
                self.playlist_view.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
                self.playlist_view.customContextMenuRequested.connect(self.show_playlist_context_menu)
                # 连接键盘事件
                self.playlist_view.keyPressEvent = self.playlist_key_press_event
                self.playlist_view.setStyleSheet("""
                    QListWidget {
                        border: 1px solid #cccccc;
                        border-radius: 5px;
                        background-color: #f8f8f8;
                    }
                    QListWidget::item {
                        padding: 5px;
                        border-bottom: 1px solid #eeeeee;
                    }
                    QListWidget::item:selected {
                        background-color: #e6f3ff;
                        color: #000000;
                    }
                    QListWidget::item:alternate {
                        background-color: #f0f0f0;
                    }
                """)
                playlist_layout.addWidget(self.playlist_view)
                
                # 添加播放列表面板到主布局
                self.main_layout.addWidget(self.playlist_panel)
                
                # 尝试加载已保存的播放列表
                try:
                    # 检查播放列表是否为空或仅包含当前文件
                    if not self.playlist or (len(self.playlist) == 1 and self.playlist[0] == file_path):
                        self.load_playlist()
                        
                        # 如果加载后播放列表仍为空或只有一个项目，则确保当前文件在列表中
                        if not self.playlist or file_path not in self.playlist:
                            # 将当前文件添加到播放列表中
                            self.playlist.append(file_path)
                            self.playlist_view.addItem(os.path.basename(file_path))
                            self.current_playlist_index = len(self.playlist) - 1
                        else:
                            # 更新当前播放索引
                            self.current_playlist_index = self.playlist.index(file_path)
                except Exception as e:
                    print(f"加载播放列表失败: {str(e)}")
            
            # 创建歌词编辑面板（如果不存在）
            if not hasattr(self, 'lyrics_panel'):
                # 创建歌词面板
                self.lyrics_panel = QWidget()
                self.lyrics_panel.setVisible(False)  # 默认隐藏
                
                # 创建歌词布局
                lyrics_layout = QVBoxLayout(self.lyrics_panel)
                
                # 创建歌词标题
                lyrics_title = QLabel("歌词编辑")
                lyrics_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
                lyrics_title.setStyleSheet("font-weight: bold; font-size: 14px;")
                lyrics_layout.addWidget(lyrics_title)
                
                # 创建歌词控制按钮布局
                lyrics_btn_layout = QHBoxLayout()
                
                # 保存歌词按钮
                self.save_lyrics_btn = QPushButton("保存歌词")
                self.save_lyrics_btn.clicked.connect(self.save_current_lyrics)
                lyrics_btn_layout.addWidget(self.save_lyrics_btn)
                
                # 清空歌词按钮
                self.clear_lyrics_btn = QPushButton("清空歌词")
                self.clear_lyrics_btn.clicked.connect(self.clear_current_lyrics)
                lyrics_btn_layout.addWidget(self.clear_lyrics_btn)
                
                # 切换显示模式按钮
                self.toggle_lyrics_mode_btn = QPushButton("动态显示")
                self.toggle_lyrics_mode_btn.setCheckable(True) 
                self.toggle_lyrics_mode_btn.clicked.connect(self.toggle_lyrics_display_mode)
                lyrics_btn_layout.addWidget(self.toggle_lyrics_mode_btn)
                
                lyrics_layout.addLayout(lyrics_btn_layout)
                
                # 创建Tab控件用于切换编辑和显示模式
                self.lyrics_tab = QTabWidget()
                
                # 创建歌词编辑器标签页
                edit_tab = QWidget()
                edit_layout = QVBoxLayout(edit_tab)
                
                # 添加歌词编辑辅助控件布局
                edit_tools_layout = QHBoxLayout()
                
                # 添加时间标签按钮
                self.add_time_tag_btn = QPushButton("插入时间标签")
                self.add_time_tag_btn.setToolTip("在当前光标位置插入时间标签 [mm:ss.xx]")
                self.add_time_tag_btn.clicked.connect(self.insert_time_tag)
                edit_tools_layout.addWidget(self.add_time_tag_btn)
                
                # 添加同步播放按钮
                self.sync_lyrics_btn = QPushButton("同步模式")
                self.sync_lyrics_btn.setCheckable(True)
                self.sync_lyrics_btn.setToolTip("听音乐时点击此按钮将自动添加当前播放时间的时间标签")
                self.sync_lyrics_btn.clicked.connect(self.toggle_sync_mode)
                edit_tools_layout.addWidget(self.sync_lyrics_btn)
                
                # 添加时间偏移调整按钮
                self.time_offset_label = QLabel("时间偏移:")
                edit_tools_layout.addWidget(self.time_offset_label)
                
                self.time_offset_spinbox = QSpinBox()
                self.time_offset_spinbox.setRange(-5000, 5000)  # 允许 -5秒 到 +5秒
                self.time_offset_spinbox.setValue(0)
                self.time_offset_spinbox.setSingleStep(100)
                self.time_offset_spinbox.setSuffix(" ms")
                self.time_offset_spinbox.setToolTip("调整插入的时间标签偏移量")
                edit_tools_layout.addWidget(self.time_offset_spinbox)
                
                # 添加歌词格式化按钮
                self.format_lyrics_btn = QPushButton("格式化歌词")
                self.format_lyrics_btn.setToolTip("整理歌词格式，每行一个时间标签")
                self.format_lyrics_btn.clicked.connect(self.format_lyrics)
                edit_tools_layout.addWidget(self.format_lyrics_btn)
                
                # 添加自动换行切换按钮
                self.auto_tag_lines_btn = QPushButton("自动标记行")
                self.auto_tag_lines_btn.setToolTip("自动为所有没有时间标签的行添加时间标签")
                self.auto_tag_lines_btn.clicked.connect(self.auto_tag_lines)
                edit_tools_layout.addWidget(self.auto_tag_lines_btn)
                
                # 添加批量调整时间标签按钮
                self.batch_adjust_btn = QPushButton("批量调整")
                self.batch_adjust_btn.setToolTip("批量调整所有时间标签")
                self.batch_adjust_btn.clicked.connect(self.show_batch_adjust_dialog)
                edit_tools_layout.addWidget(self.batch_adjust_btn)
                
                # 添加帮助按钮
                self.lyrics_help_btn = QPushButton("帮助")
                self.lyrics_help_btn.setToolTip("显示歌词编辑帮助")
                self.lyrics_help_btn.clicked.connect(self.show_lyrics_help)
                edit_tools_layout.addWidget(self.lyrics_help_btn)
                
                edit_layout.addLayout(edit_tools_layout)
                
                # 创建歌词编辑器
                self.lyrics_editor = LyricTextEdit(self)
                self.lyrics_editor.set_main_window(self)
                self.lyrics_editor.setStyleSheet("""
                    QTextEdit {
                        border: 1px solid #cccccc;
                        border-radius: 5px;
                        background-color: #ffffff;
                        font-family: "Microsoft YaHei", Arial, sans-serif;
                        font-size: 12pt;
                        line-height: 1.5;
                        padding: 10px;
                    }
                """)
                
                # 添加歌词同步提示区域
                self.sync_info_label = QLabel("同步模式关闭")
                self.sync_info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                self.sync_info_label.setStyleSheet("""
                    QLabel {
                        background-color: #f8f8f8;
                        border: 1px solid #ddd;
                        border-radius: 3px;
                        padding: 5px;
                        font-weight: bold;
                        color: #666;
                    }
                """)
                self.sync_info_label.setVisible(False)  # 默认隐藏
                edit_layout.addWidget(self.sync_info_label)
                
                edit_layout.addWidget(self.lyrics_editor)
                self.lyrics_tab.addTab(edit_tab, "编辑歌词")
                
                # 创建动态歌词显示标签页
                display_tab = QWidget()
                display_layout = QVBoxLayout(display_tab)
                
                # 创建动态歌词列表
                self.lyrics_list = QListWidget()
                self.lyrics_list.setStyleSheet("""
                    QListWidget {
                        border: 1px solid #cccccc;
                        border-radius: 5px;
                        background-color: #fafafa;
                        font-family: "Microsoft YaHei", Arial, sans-serif;
                        font-size: 12pt;
                        line-height: 1.8;
                        padding: 10px;
                    }
                    QListWidget::item {
                        padding: 5px;
                        border: none;
                    }
                    QListWidget::item:selected {
                        background-color: #e6f3ff;
                        color: #1976D2;
                        font-weight: bold;
                        font-size: 14pt;
                    }
                """)
                self.lyrics_list.setVerticalScrollMode(QListWidget.ScrollMode.ScrollPerPixel)
                self.lyrics_list.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
                self.lyrics_list.setWordWrap(True)  # 允许文本换行
                # 添加双击事件，实现歌词跳转
                self.lyrics_list.itemDoubleClicked.connect(self.on_sidebar_lyric_double_clicked)
                display_layout.addWidget(self.lyrics_list)
                self.lyrics_tab.addTab(display_tab, "动态歌词")
                
                lyrics_layout.addWidget(self.lyrics_tab)
                
                # 添加歌词面板到主布局
                self.main_layout.addWidget(self.lyrics_panel)
            
            # 将文件添加到播放列表（如果尚未添加）
            if file_path not in self.playlist:
                self.playlist.append(file_path)
                self.playlist_view.addItem(os.path.basename(file_path))
            
            # 设置当前播放索引
            self.current_playlist_index = self.playlist.index(file_path)
            
            # 高亮显示当前播放的项目
            self.update_playlist_highlight()
            
            # 加载并显示歌词
            self.current_lyrics = self.get_lyrics_for_music(file_path)
            self.lyrics_editor.setText(self.current_lyrics)
            
            # 连接媒体播放器信号
            self.media_player.positionChanged.connect(self.position_changed)
            self.media_player.durationChanged.connect(self.duration_changed)
            self.media_player.playbackStateChanged.connect(self.state_changed)
            self.media_player.mediaStatusChanged.connect(self.media_status_changed)
            
            # 设置初始状态
            self.is_playing = False
            self.play_btn.setText("播放")
            
            # 恢复保存的播放位置
            self.restore_file_state(file_path)
            
            # 更新状态栏
            self.statusBar.showMessage(f"音乐文件: {os.path.basename(file_path)}")
            self.update_statusbar_for_file_type()
            self.file_type_label.setText(f"音乐文件 | {os.path.splitext(file_path)[1][1:].upper()}")
            
        except Exception as e:
            raise Exception(f"无法加载音乐文件：{str(e)}")
    
    def display_audio_cover(self, file_path):
        """显示音乐封面或默认音乐图标"""
        try:
            # 检查是否有保存的自定义封面
            custom_cover = None
            if file_path in self.file_states and 'custom_cover' in self.file_states[file_path]:
                custom_cover = self.file_states[file_path]['custom_cover']
            
            # 获取预览区域的大小
            preview_size = self.preview_area.size()
            available_width = preview_size.width() - 20  # 减去一些边距
            available_height = preview_size.height() - 20  # 减去一些边距
            
            # 确保至少有一个最小尺寸
            if available_width < 200:
                available_width = 200
            if available_height < 200:
                available_height = 200
                
            # 如果有自定义封面且文件存在，则使用自定义封面
            if custom_cover and os.path.exists(custom_cover):
                try:
                    pixmap = QPixmap(custom_cover)
                    if not pixmap.isNull():
                        # 缩放图片以适应显示区域，保持纵横比
                        pixmap = pixmap.scaled(
                            available_width, available_height,
                            Qt.AspectRatioMode.KeepAspectRatio,
                            Qt.TransformationMode.SmoothTransformation
                        )
                    else:
                        # 如果加载失败，使用默认图标
                        raise Exception("无法加载自定义封面")
                except Exception:
                    # 如果加载自定义封面失败，删除无效的自定义封面记录
                    if file_path in self.file_states and 'custom_cover' in self.file_states[file_path]:
                        del self.file_states[file_path]['custom_cover']
                        self.save_file_state(file_path)
                    # 使用默认图标
                    pixmap = self.create_default_music_icon(available_width, available_height)
            else:
                # 使用默认图标
                pixmap = self.create_default_music_icon(available_width, available_height)
            
            # 设置图片到标签
            self.image_label.setPixmap(pixmap)
            
            # 将图片居中显示
            self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            
            # 设置图片标签的大小策略，使其能够占满可用空间
            from PyQt6.QtWidgets import QSizePolicy
            self.image_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
            
            # 更新音乐文件信息到状态栏
            file_size = os.path.getsize(file_path)
            size_str = self.format_file_size(file_size)
            self.file_info_label.setText(f"文件大小: {size_str}")
            
        except Exception as e:
            print(f"显示音乐封面错误: {str(e)}")
            
    def create_default_music_icon(self, width=200, height=200):
        """创建默认音乐图标
        
        Args:
            width: 图标宽度
            height: 图标高度
        """
        # 使用较大的尺寸以保证图标清晰
        size = max(width, height, 200)
        pixmap = QPixmap(size, size)
        pixmap.fill(Qt.GlobalColor.transparent)
        
        painter = QPainter(pixmap)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        
        # 计算边距和圆形大小
        margin = int(size * 0.05)  # 边距为总尺寸的5%
        circle_size = int(size - 2 * margin)
        
        # 绘制圆形背景
        gradient = QLinearGradient(0, 0, size, size)
        gradient.setColorAt(0, QColor("#1976D2"))  # 深蓝色
        gradient.setColorAt(1, QColor("#03A9F4"))  # 浅蓝色
        painter.setBrush(gradient)
        painter.setPen(Qt.PenStyle.NoPen)
        painter.drawEllipse(margin, margin, circle_size, circle_size)
        
        # 计算音符的位置和大小
        note_scale = size / 200  # 以原始200px为基准的缩放比例
        pen_width = max(2, int(5 * note_scale))  # 确保线条宽度至少为2像素
        
        # 绘制音乐符号
        painter.setPen(QPen(QColor("#FFFFFF"), pen_width))
        
        # 音符头
        note_head_x = int(size * 0.3)
        note_head_y = int(size * 0.5)
        note_head_w = int(size * 0.1)
        note_head_h = int(size * 0.075)
        painter.drawEllipse(note_head_x, note_head_y, note_head_w, note_head_h)
        
        # 音符竖线
        stem_x = int(note_head_x + note_head_w)
        painter.drawLine(stem_x, int(note_head_y + note_head_h/2), stem_x, int(note_head_y - note_head_h))
        
        # 音符横线
        beam_y = int(note_head_y - note_head_h)
        beam_end_x = int(size * 0.7)
        beam_end_y = int(size * 0.225)
        painter.drawLine(stem_x, beam_y, beam_end_x, beam_end_y)
        
        # 音符头2
        note_head2_x = int(size * 0.6)
        note_head2_y = int(size * 0.225)
        painter.drawEllipse(note_head2_x, note_head2_y, note_head_w, note_head_h)
        
        # 音符竖线2
        stem2_x = int(note_head2_x + note_head_w)
        painter.drawLine(stem2_x, int(note_head2_y + note_head_h/2), stem2_x, int(note_head2_y + note_head_h*2))
        
        painter.end()
        
        # 如果请求的尺寸与创建的尺寸不同，则缩放图标
        if width != size or height != size:
            pixmap = pixmap.scaled(width, height, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
        
        return pixmap
            
    def format_duration(self, duration):
        """将毫秒转换为时分秒格式"""
        seconds = int(duration / 1000) % 60
        minutes = int(duration / 60000) % 60
        hours = int(duration / 3600000)
        
        if hours > 0:
            return f"{hours}:{minutes:02d}:{seconds:02d}"
        else:
            return f"{minutes:02d}:{seconds:02d}"

    def update_playlist_highlight(self):
        """更新播放列表中当前播放项目的高亮显示"""
        # 确保播放列表视图已创建
        if not hasattr(self, 'playlist_view'):
            return
            
        # 清除所有项目的高亮
        for i in range(self.playlist_view.count()):
            item = self.playlist_view.item(i)
            item.setBackground(QColor(0, 0, 0, 0))  # 透明背景
            font = item.font()
            font.setBold(False)
            item.setFont(font)
        
        # 设置当前播放项目的高亮
        if 0 <= self.current_playlist_index < len(self.playlist):
            item = self.playlist_view.item(self.current_playlist_index)
            if item:
                item.setBackground(QColor("#d4eaff"))  # 浅蓝色背景
                font = item.font()
                font.setBold(True)
                item.setFont(font)
                # 确保当前项目可见
                self.playlist_view.scrollToItem(item)
    
    def media_status_changed(self, status):
        """媒体状态改变时的处理函数"""
        # 当媒体播放结束时
        if status == QMediaPlayer.MediaStatus.EndOfMedia:
            # 根据播放模式选择下一曲
            if self.play_mode == "sequence":
                # 顺序播放，如果已经是最后一曲，则停止
                if self.current_playlist_index < len(self.playlist) - 1:
                    self.play_next()
            elif self.play_mode == "loop":
                # 循环播放，如果是最后一曲，则回到第一曲
                self.play_next()
            elif self.play_mode == "random":
                # 随机播放
                if len(self.playlist) > 1:
                    import random
                    next_index = random.randint(0, len(self.playlist) - 1)
                    # 避免随机到当前曲目
                    while next_index == self.current_playlist_index and len(self.playlist) > 1:
                        next_index = random.randint(0, len(self.playlist) - 1)
                    self.play_playlist_item(next_index)
    
    def play_previous(self):
        """播放上一曲"""
        if not self.playlist:
            return
        
        if self.play_mode == "random":
            # 随机模式下也按顺序播放上一曲
            prev_index = (self.current_playlist_index - 1) % len(self.playlist)
            self.play_playlist_item(prev_index)
        else:
            # 顺序播放和循环播放模式
            prev_index = (self.current_playlist_index - 1) % len(self.playlist)
            self.play_playlist_item(prev_index)
    
    def play_next(self):
        """播放下一曲"""
        if not self.playlist:
            return
        
        if self.play_mode == "random":
            # 随机播放模式
            import random
            next_index = random.randint(0, len(self.playlist) - 1)
            # 避免随机到当前曲目
            while next_index == self.current_playlist_index and len(self.playlist) > 1:
                next_index = random.randint(0, len(self.playlist) - 1)
            self.play_playlist_item(next_index)
        else:
            # 顺序播放和循环播放模式
            next_index = (self.current_playlist_index + 1) % len(self.playlist)
            self.play_playlist_item(next_index)
    
    def play_playlist_item(self, index):
        """播放播放列表中指定索引的音乐"""
        if 0 <= index < len(self.playlist):
            file_path = self.playlist[index]
            
            # 保存当前文件状态
            if self.current_file:
                self.save_file_state(self.current_file)
            
            # 更新当前播放索引
            self.current_playlist_index = index
            
            # 高亮显示当前播放的项目
            self.update_playlist_highlight()
            
            try:
                # 设置音频源
                self.media_player.setSource(QUrl.fromLocalFile(file_path))
                
                # 更新音乐封面
                self.display_audio_cover(file_path)
                
                # 设置当前文件
                self.current_file = file_path
                
                # 恢复保存的播放位置
                self.restore_file_state(file_path)
                
                # 自动开始播放
                self.media_player.play()
                self.play_btn.setText("暂停")
                self.is_playing = True
                
                # 更新状态栏
                self.statusBar.showMessage(f"音乐文件: {os.path.basename(file_path)}")
                self.update_statusbar_for_file_type()
                self.file_type_label.setText(f"音乐文件 | {os.path.splitext(file_path)[1][1:].upper()}")
                
                # 更新歌词显示
                if hasattr(self, 'lyrics_editor'):
                    # 重置歌词索引
                    self.current_lyric_index = -1
                    
                    # 获取并显示歌词
                    self.current_lyrics = self.get_lyrics_for_music(file_path)
                    self.lyrics_editor.setText(self.current_lyrics)
                    
                                    # 如果中央歌词显示正在显示，刷新中央歌词显示
                if hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
                    # 更新歌曲标题
                    if hasattr(self, 'song_info_label'):
                        self.song_info_label.setText(os.path.basename(file_path))
                    
                    # 确保歌词数据已加载
                    if not self.current_lyrics and hasattr(self, 'lyrics_dict'):
                        self.current_lyrics = self.get_lyrics_for_music(file_path)
                    
                    # 更新歌词内容
                    self.update_center_lyrics_display()
                    
                    # 清除所有选择，直到播放器的positionChanged事件被触发
                    if hasattr(self, 'center_lyrics_list'):
                        self.center_lyrics_list.clearSelection()
            except Exception as e:
                QMessageBox.warning(self, "播放错误", f"无法播放文件: {file_path}\n错误: {str(e)}")
                # 尝试播放下一曲
                if self.play_mode != "random":
                    next_index = (index + 1) % len(self.playlist)
                    if next_index != index:  # 避免无限循环
                        self.play_playlist_item(next_index)
    
    def playlist_item_double_clicked(self, item):
        """双击播放列表项目时播放相应的音乐"""
        index = self.playlist_view.row(item)
        self.play_playlist_item(index)
    
    def toggle_play_mode(self):
        """切换播放模式（顺序、循环、随机）"""
        if self.play_mode == "sequence":
            self.play_mode = "loop"
            self.play_mode_btn.setText("循环播放")
        elif self.play_mode == "loop":
            self.play_mode = "random"
            self.play_mode_btn.setText("随机播放")
        else:
            self.play_mode = "sequence"
            self.play_mode_btn.setText("顺序播放")
    
    def toggle_playlist_panel(self):
        """切换播放列表面板的显示状态"""
        # 切换播放列表面板的可见性
        should_show = not self.playlist_panel.isVisible()
        self.playlist_panel.setVisible(should_show)
        
        # 如果是要显示播放列表并且播放列表为空，尝试加载播放列表
        if should_show and (not self.playlist or self.playlist_view.count() == 0):
            try:
                self.load_playlist()
                # 如果播放列表加载成功但UI没有更新，手动更新UI
                if self.playlist and self.playlist_view.count() == 0:
                    self.playlist_view.clear()
                    for file_path in self.playlist:
                        self.playlist_view.addItem(os.path.basename(file_path))
                    
                    # 更新高亮显示
                    self.update_playlist_highlight()
                    
                    # 显示加载成功的消息
                    self.statusBar.showMessage("播放列表加载成功", 3000)
            except Exception as e:
                print(f"点击播放列表按钮时加载播放列表失败: {str(e)}")
                self.statusBar.showMessage("播放列表加载失败", 3000)
    
    def add_to_playlist(self):
        """添加音乐文件到播放列表"""
        file_paths, _ = QFileDialog.getOpenFileNames(
            self,
            "添加音乐到播放列表",
            "",
            "音频文件 (*.mp3 *.wav *.ogg *.flac *.aac *.m4a *.wma);;所有文件 (*)"
        )
        
        if file_paths:
            for file_path in file_paths:
                # 避免重复添加
                if file_path not in self.playlist:
                    self.playlist.append(file_path)
                    self.playlist_view.addItem(os.path.basename(file_path))
            
            # 如果当前没有播放音乐，则自动播放第一个添加的文件
            if self.current_playlist_index == -1 and self.playlist:
                self.current_playlist_index = 0
                self.play_playlist_item(0)
    
    def clear_playlist(self):
        """清空播放列表"""
        # 询问用户是否确认清空
        reply = QMessageBox.question(
            self,
            "清空播放列表",
            "确定要清空播放列表吗？",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            # 停止播放
            self.media_player.stop()
            self.is_playing = False
            self.play_btn.setText("播放")
            
            # 清空播放列表
            self.playlist.clear()
            self.playlist_view.clear()
            self.current_playlist_index = -1
    
    def save_playlist(self):
        """保存播放列表到文件"""
        # 这个功能可以扩展，将播放列表保存到文件中，以便下次启动时恢复
        if not self.playlist:
            return
        
        try:
            # 创建数据目录（如果不存在）
            data_dir = os.path.join(os.path.expanduser("~"), ".gofile")
            os.makedirs(data_dir, exist_ok=True)
            
            # 保存播放列表
            playlist_file = os.path.join(data_dir, "playlist.json")
            with open(playlist_file, "w", encoding="utf-8") as f:
                data = {
                    "playlist": self.playlist,
                    "current_index": self.current_playlist_index,
                    "play_mode": self.play_mode
                }
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存播放列表失败: {str(e)}")
    
    def load_playlist(self):
        """从文件加载播放列表"""
        try:
            # 尝试加载播放列表
            playlist_file = os.path.join(os.path.expanduser("~"), ".gofile", "playlist.json")
            if os.path.exists(playlist_file):
                with open(playlist_file, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    
                    # 恢复播放列表
                    loaded_playlist = data.get("playlist", [])
                    
                    # 检查文件是否存在，移除不存在的文件
                    valid_playlist = []
                    missing_files = []
                    
                    for file_path in loaded_playlist:
                        if os.path.exists(file_path):
                            valid_playlist.append(file_path)
                        else:
                            missing_files.append(file_path)
                    
                    # 更新播放列表和索引
                    self.playlist = valid_playlist
                    self.current_playlist_index = data.get("current_index", -1)
                    
                    # 如果当前索引超出了有效播放列表的范围，重置索引
                    if self.current_playlist_index >= len(self.playlist):
                        self.current_playlist_index = -1
                    
                    self.play_mode = data.get("play_mode", "sequence")
                    
                    # 只有在播放模式按钮存在时才更新它
                    if hasattr(self, 'play_mode_btn'):
                        if self.play_mode == "sequence":
                            self.play_mode_btn.setText("顺序播放")
                        elif self.play_mode == "loop":
                            self.play_mode_btn.setText("循环播放")
                        else:
                            self.play_mode_btn.setText("随机播放")
                    
                    # 只有在播放列表视图存在时才更新它
                    if hasattr(self, 'playlist_view'):
                        self.playlist_view.clear()
                        for file_path in self.playlist:
                            self.playlist_view.addItem(os.path.basename(file_path))
                        
                        # 只有在播放列表有内容时才更新高亮显示
                        if self.playlist:
                            self.update_playlist_highlight()
                    
                    # 如果有不存在的文件，显示提示并保存更新后的播放列表
                    if missing_files:
                        print(f"播放列表中有 {len(missing_files)} 个文件不存在，已从列表中移除")
                        # 自动保存清理后的播放列表
                        self.save_playlist()
        except Exception as e:
            print(f"加载播放列表失败: {str(e)}")
    
    def closeEvent(self, event):
        """窗口关闭事件处理，保存播放列表和当前状态"""
        # 停止视频播放
        if hasattr(self, 'media_player') and self.media_player.playbackState() != QMediaPlayer.PlaybackState.StoppedState:
            self.media_player.stop()
        
        # 检查是否有未保存的修改
        if hasattr(self, 'text_modified') and self.text_modified:
            reply = QMessageBox.question(
                self,
                "保存更改",
                "文件已被修改，是否保存更改？",
                QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel
            )
            
            if reply == QMessageBox.StandardButton.Save:
                if not self.save_file():
                    event.ignore()
                    return
            elif reply == QMessageBox.StandardButton.Cancel:
                event.ignore()
                return
        
        # 保存当前文件状态
        if self.current_file:
            try:
                self.save_file_state(self.current_file)
            except Exception as e:
                print(f"保存文件状态失败: {str(e)}")
        
        # 保存当前歌词和歌词数据
        try:
            self.save_current_lyrics()
            self.save_lyrics()
        except Exception as e:
            print(f"保存歌词失败: {str(e)}")
        
        # 保存播放列表
        try:
            self.save_playlist()
        except Exception as e:
            print(f"保存播放列表失败: {str(e)}")
        
        # 保存最近文件
        try:
            self.save_recent_files()
        except Exception as e:
            print(f"保存最近文件失败: {str(e)}")
        
        # 从窗口列表中移除此窗口
        global all_windows
        if self in all_windows:
            all_windows.remove(self)
        
        # 更新其他窗口的窗口菜单
        for window in all_windows:
            if window != self and window.isVisible():
                try:
                    window.refresh_window_menu()
                except:
                    pass  # 防止任何异常
        
        # 只有在没有可见窗口时才退出应用程序
        visible_windows = [w for w in all_windows if w.isVisible()]
        if not visible_windows:
            print("所有窗口已关闭，退出应用程序")
            # 稍微延迟退出，确保当前窗口已完全关闭
            QTimer.singleShot(100, QApplication.quit)
        
        # 接受关闭事件
        event.accept()

    def save_lyrics(self):
        """保存所有歌词到文件"""
        try:
            # 创建数据目录（如果不存在）
            data_dir = os.path.dirname(self.lyrics_file_path)
            os.makedirs(data_dir, exist_ok=True)
            
            # 保存歌词数据
            with open(self.lyrics_file_path, "w", encoding="utf-8") as f:
                json.dump(self.lyrics_dict, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存歌词失败: {str(e)}")
    
    def load_lyrics(self):
        """从文件加载所有歌词"""
        try:
            if os.path.exists(self.lyrics_file_path):
                with open(self.lyrics_file_path, "r", encoding="utf-8") as f:
                    self.lyrics_dict = json.load(f)
        except Exception as e:
            print(f"加载歌词失败: {str(e)}")
    
    def get_lyrics_for_music(self, file_path):
        """获取指定音乐文件的歌词"""
        lyrics_text = self.lyrics_dict.get(file_path, "")
        
        # 如果有歌词，解析时间标签
        if lyrics_text:
            self.timed_lyrics = self.parse_lrc_lyrics(lyrics_text)
            # 重置当前歌词索引
            self.current_lyric_index = -1
            
            # 如果正在动态显示模式，更新歌词显示
            if hasattr(self, 'toggle_lyrics_mode_btn') and self.toggle_lyrics_mode_btn.isChecked():
                self.update_lyrics_display()
                
            # 如果中央歌词显示正在显示，也更新中央歌词
            if hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
                # 更新歌曲标题
                if hasattr(self, 'song_info_label') and file_path:
                    self.song_info_label.setText(os.path.basename(file_path))
                
                # 更新歌词内容
                self.update_center_lyrics_display()
        else:
            # 如果没有歌词，清空时间标签字典
            self.timed_lyrics = {}
            
            # 同样更新歌词显示（清空歌词）
            if hasattr(self, 'toggle_lyrics_mode_btn') and self.toggle_lyrics_mode_btn.isChecked():
                self.update_lyrics_display()
                
            # 如果中央歌词显示正在显示，也更新中央歌词
            if hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
                # 更新歌曲标题
                if hasattr(self, 'song_info_label') and file_path:
                    self.song_info_label.setText(os.path.basename(file_path))
                
                # 更新歌词内容
                self.update_center_lyrics_display()
        
        return lyrics_text
    
    def save_current_lyrics(self):
        """保存当前歌词"""
        # 如果没有播放列表或当前文件不是播放列表中的文件，则不执行任何操作
        if not hasattr(self, 'playlist') or not self.playlist:
            return
            
        if not hasattr(self, 'current_file') or not self.current_file:
            return
            
        if self.current_file and self.current_file in self.playlist:
            # 获取当前歌词编辑区的内容
            if hasattr(self, 'lyrics_editor') and self.lyrics_editor.isVisible():
                lyrics_text = self.lyrics_editor.toPlainText()
                self.lyrics_dict[self.current_file] = lyrics_text
                self.current_lyrics = lyrics_text
                
                # 解析时间标签，更新动态歌词
                self.timed_lyrics = self.parse_lrc_lyrics(lyrics_text)
                self.current_lyric_index = -1
                
                # 如果正在动态显示模式，更新歌词显示
                if hasattr(self, 'toggle_lyrics_mode_btn') and self.toggle_lyrics_mode_btn.isChecked():
                    self.update_lyrics_display()
                
                # 保存到文件
                self.save_lyrics()
                # 显示保存成功消息
                self.statusBar.showMessage("歌词保存成功", 3000)

    def toggle_lyrics_panel(self):
        """切换歌词面板的显示状态"""
        if hasattr(self, 'lyrics_panel'):
            self.lyrics_panel.setVisible(not self.lyrics_panel.isVisible())
    
    def clear_current_lyrics(self):
        """清空当前歌词"""
        if hasattr(self, 'lyrics_editor'):
            # 询问用户是否确认清空
            reply = QMessageBox.question(
                self,
                "清空歌词",
                "确定要清空当前歌词吗？",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                self.lyrics_editor.clear()
                if self.current_file and self.current_file in self.playlist:
                    # 更新歌词字典，设置为空字符串
                    self.lyrics_dict[self.current_file] = ""
                    self.current_lyrics = ""
                    
                    # 清空动态歌词
                    self.timed_lyrics = {}
                    self.current_lyric_index = -1
                    
                    # 清空动态歌词列表
                    if hasattr(self, 'lyrics_list'):
                        self.lyrics_list.clear()
                    
                    # 保存到文件
                    self.save_lyrics()
                    # 显示消息
                    self.statusBar.showMessage("歌词已清空", 3000)

    def show_playlist_context_menu(self, pos):
        """显示播放列表的上下文菜单"""
        # 获取点击位置的项目
        item = self.playlist_view.itemAt(pos)
        if not item:
            return
            
        # 创建上下文菜单
        menu = QMenu()
        
        # 播放选项
        play_action = QAction("播放")
        play_action.triggered.connect(lambda: self.play_playlist_item(self.playlist_view.row(item)))
        menu.addAction(play_action)
        
        # 删除选项
        delete_action = QAction("删除")
        delete_action.triggered.connect(lambda: self.delete_playlist_item(self.playlist_view.row(item)))
        menu.addAction(delete_action)
        
        # 显示菜单
        menu.exec(self.playlist_view.mapToGlobal(pos))
    
    def delete_playlist_item(self, index):
        """删除播放列表中的项目"""
        if index < 0 or index >= len(self.playlist):
            return
        
        # 保存要删除的项目名称，用于后续显示
        deleted_item_name = os.path.basename(self.playlist[index])    
            
        reply = QMessageBox.question(
            self,
            "删除项目",
            f"确定要删除 '{deleted_item_name}' 吗？",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            # 如果要删除的是当前正在播放的项目
            is_playing_item = (index == self.current_playlist_index)
            
            # 删除项目
            del self.playlist[index]
            self.playlist_view.takeItem(index)
            
            # 保存播放列表
            self.save_playlist()
            
            # 更新当前播放索引
            if is_playing_item:
                # 如果正在播放，且删除的是当前项目，则停止播放
                self.media_player.stop()
                self.is_playing = False
                self.play_btn.setText("播放")
                
                # 如果播放列表还有内容，更新索引为-1，否则可以从头开始播放
                if self.playlist:
                    if index < len(self.playlist):
                        # 自动播放下一首
                        self.play_playlist_item(index)
                    else:
                        # 如果是最后一项，则播放第一项
                        self.play_playlist_item(0)
                else:
                    self.current_playlist_index = -1
            elif index < self.current_playlist_index:
                # 如果删除的项目在当前播放项目之前，则调整当前播放索引
                self.current_playlist_index -= 1
            
            # 更新播放列表高亮
            self.update_playlist_highlight()
            
            # 显示删除成功提示
            self.statusBar.showMessage(f"已从播放列表中删除 '{deleted_item_name}'", 3000)

    def playlist_key_press_event(self, event):
        """处理播放列表的键盘事件"""
        # 处理Delete键删除选中的项目
        if event.key() == Qt.Key.Key_Delete:
            current_item = self.playlist_view.currentItem()
            if current_item:
                index = self.playlist_view.row(current_item)
                self.delete_playlist_item(index)
        # 处理Enter键或空格键播放选中的项目
        elif event.key() in [Qt.Key.Key_Return, Qt.Key.Key_Enter, Qt.Key.Key_Space]:
            current_item = self.playlist_view.currentItem()
            if current_item:
                index = self.playlist_view.row(current_item)
                self.play_playlist_item(index)
        # 其他键盘事件传递给原始的事件处理函数
        else:
            QListWidget.keyPressEvent(self.playlist_view, event)

    def parse_lrc_lyrics(self, lyrics_text):
        """
        解析LRC格式歌词
        返回一个格式为 {时间(毫秒): 歌词文本} 的字典
        """
        lyrics_dict = {}
        if not lyrics_text:
            return lyrics_dict
            
        # 匹配时间标签 [mm:ss.xx] 或 [mm:ss]
        time_pattern = re.compile(r'\[(\d{2}):(\d{2})(\.\d{2})?\]')
        
        for line in lyrics_text.split('\n'):
            line = line.strip()
            if not line:
                continue
                
            # 跳过歌曲信息行（以[ar:],[ti:],[al:],[by:]等开头）
            if line.startswith('[ar:') or line.startswith('[ti:') or line.startswith('[al:') or line.startswith('[by:'):
                continue
                
            # 查找所有时间标签
            time_tags = time_pattern.findall(line)
            if not time_tags:
                continue
                
            # 提取歌词文本（去掉所有时间标签）
            lyric_text = time_pattern.sub('', line).strip()
            
            # 将时间标签转换为毫秒，并与歌词文本关联
            for tag in time_tags:
                minutes = int(tag[0])
                seconds = int(tag[1])
                milliseconds = int(tag[2][1:]) * 10 if tag[2] else 0
                
                # 转换为总毫秒
                total_ms = minutes * 60 * 1000 + seconds * 1000 + milliseconds
                
                # 存储时间与歌词的映射
                lyrics_dict[total_ms] = lyric_text
                
        return lyrics_dict

    def toggle_lyrics_display_mode(self, checked):
        """切换歌词显示模式"""
        # 切换到相应的标签页
        if checked:
            # 切换到动态歌词显示标签页
            self.lyrics_tab.setCurrentIndex(1)
            
            # 如果有当前歌词和正在播放的音乐，解析歌词并显示
            if self.current_lyrics and self.current_file:
                self.timed_lyrics = self.parse_lrc_lyrics(self.current_lyrics)
                self.update_lyrics_display()
        else:
            # 切换到歌词编辑标签页
            self.lyrics_tab.setCurrentIndex(0)
    
    def update_lyrics_display(self):
        """更新动态歌词显示（侧边栏）"""
        # 清空歌词列表
        self.lyrics_list.clear()
        
        # 如果没有时间标签的歌词，直接显示为普通文本
        if not self.timed_lyrics:
            # 将普通歌词按行分割并添加到列表
            for line in self.current_lyrics.split('\n'):
                if line.strip():
                    self.lyrics_list.addItem(line.strip())
            return
        
        # 有时间标签的歌词，按时间排序
        sorted_lyrics = sorted(self.timed_lyrics.items())
        
        # 添加到列表
        for _, lyric_text in sorted_lyrics:
            if lyric_text.strip():
                self.lyrics_list.addItem(lyric_text.strip())
            else:
                # 如果是空行，添加一个空格确保项目高度正确
                self.lyrics_list.addItem(" ")
        
        # 如果有选中的歌词，确保其可见
        if self.current_lyric_index >= 0 and self.current_lyric_index < self.lyrics_list.count():
            self.lyrics_list.scrollToItem(self.lyrics_list.item(self.current_lyric_index))
            
        # 如果中央歌词显示也在显示，同时更新中央歌词
        if hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
            self.update_center_lyrics_display()
    
    def update_current_lyric(self, position):
        """根据当前播放位置更新显示的歌词"""
        try:
            # 如果没有时间标签的歌词，不处理
            if not self.timed_lyrics:
                return
            
            # 找到当前时间对应的歌词
            current_position = position
            lyrics_times = sorted(self.timed_lyrics.keys())
            
            # 找到小于当前位置的最大时间点
            current_time = 0
            for time in lyrics_times:
                if time <= current_position:
                    current_time = time
                else:
                    break
            
            # 获取当前歌词索引
            sorted_lyrics = sorted(self.timed_lyrics.items())
            current_index = -1
            
            for i, (time, _) in enumerate(sorted_lyrics):
                if time == current_time:
                    current_index = i
                    break
            
            # 如果歌词索引有变化，则更新显示
            if current_index != self.current_lyric_index and current_index >= 0:
                self.current_lyric_index = current_index
                
                # 更新侧边栏歌词高亮
                if hasattr(self, 'lyrics_list') and self.lyrics_list.isVisible():
                    # 清除所有选择
                    self.lyrics_list.clearSelection()
                    
                    # 设置当前歌词为选中状态
                    if current_index < self.lyrics_list.count():
                        self.lyrics_list.setCurrentRow(current_index)
                        
                        # 确保当前歌词在可见区域的中央
                        self.lyrics_list.scrollToItem(
                            self.lyrics_list.item(current_index),
                            QListWidget.ScrollHint.PositionAtCenter
                        )
                
                # 更新中央歌词高亮
                if hasattr(self, 'center_lyrics_list') and hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
                    self.update_center_lyric_highlight(current_index)
                
                # 更新桌面歌词
                try:
                    if hasattr(self, 'desktop_lyric_enabled') and self.desktop_lyric_enabled:
                        if hasattr(self, 'desktop_lyric_window') and self.desktop_lyric_window and self.desktop_lyric_window.isVisible():
                            current_lyric = sorted_lyrics[current_index][1]
                            
                            # 获取下一句歌词
                            next_lyric = ""
                            if current_index + 1 < len(sorted_lyrics):
                                next_lyric = sorted_lyrics[current_index + 1][1]
                            
                            # 更新桌面歌词
                            self.desktop_lyric_window.update_lyric(current_lyric, next_lyric)
                except Exception as e:
                    # 桌面歌词更新失败，记录但不中断播放
                    print(f"桌面歌词更新失败: {str(e)}")
        except Exception as e:
            # 捕获所有异常，防止影响正常播放
            print(f"更新歌词出错: {str(e)}")

    def display_center_lyrics(self, show=True):
        """在中央区域显示动态歌词，替代音乐封面"""
        # 创建中央歌词显示部件（如果不存在）
        if not hasattr(self, 'center_lyrics_widget'):
            # 创建中央歌词显示容器
            self.center_lyrics_widget = QWidget()
            center_lyrics_layout = QVBoxLayout(self.center_lyrics_widget)
            center_lyrics_layout.setContentsMargins(10, 10, 10, 10)
            
            # 创建歌曲信息显示
            self.song_info_label = QLabel()
            self.song_info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            self.song_info_label.setStyleSheet("""
                QLabel {
                    font-family: 'Microsoft YaHei', Arial;
                    font-size: 18px;
                    font-weight: bold;
                    color: #333333;
                    margin-bottom: 10px;
                }
            """)
            center_lyrics_layout.addWidget(self.song_info_label)
            
            # 创建动态歌词列表（与侧边栏相似，但样式不同）
            self.center_lyrics_list = QListWidget()
            
            # 初始化样式，后续会通过update_center_lyrics_font_size方法更新
            self.update_center_lyrics_font_size()
            
            self.center_lyrics_list.setVerticalScrollMode(QListWidget.ScrollMode.ScrollPerPixel)
            self.center_lyrics_list.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
            self.center_lyrics_list.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
            self.center_lyrics_list.setWordWrap(True)
            self.center_lyrics_list.setFocusPolicy(Qt.FocusPolicy.NoFocus)
            # 连接双击事件，实现歌词跳转
            self.center_lyrics_list.itemDoubleClicked.connect(self.on_lyric_double_clicked)
            center_lyrics_layout.addWidget(self.center_lyrics_list, 1)
            
            # 添加到预览区域
            self.preview_layout.addWidget(self.center_lyrics_widget)
            self.center_lyrics_widget.setVisible(False)
        
        # 根据请求显示或隐藏
        if show:
            # 隐藏图片标签，显示中央歌词
            self.image_label.setVisible(False)
            self.center_lyrics_widget.setVisible(True)
            
            # 更新歌曲信息
            if self.current_file:
                self.song_info_label.setText(os.path.basename(self.current_file))
            
            # 更新中央歌词列表
            self.update_center_lyrics_display()
        else:
            # 显示图片标签，隐藏中央歌词
            self.image_label.setVisible(True)
            self.center_lyrics_widget.setVisible(False)

    def update_center_lyrics_display(self):
        """更新中央歌词显示"""
        # 确保中央歌词组件已创建
        if not hasattr(self, 'center_lyrics_list'):
            return
            
        # 清空歌词列表和选择状态
        self.center_lyrics_list.clear()
        self.center_lyrics_list.clearSelection()
        
        # 如果没有歌词，显示提示
        if not self.current_lyrics:
            item = QListWidgetItem("暂无歌词")
            # 设置列表项文本水平居中
            item.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
            self.center_lyrics_list.addItem(item)
            return
        
        # 如果没有时间标签的歌词，按行显示
        if not self.timed_lyrics:
            # 将普通歌词按行分割并添加到列表
            for line in self.current_lyrics.split('\n'):
                if line.strip():
                    item = QListWidgetItem(line.strip())
                    # 设置列表项文本水平居中
                    item.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
                    self.center_lyrics_list.addItem(item)
            return
        
        # 有时间标签的歌词，按时间排序
        sorted_lyrics = sorted(self.timed_lyrics.items())
        
        # 添加到列表（前后各添加几个空行以便滚动显示）
        empty_item1 = QListWidgetItem("")
        empty_item1.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
        self.center_lyrics_list.addItem(empty_item1)
        
        empty_item2 = QListWidgetItem("")
        empty_item2.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
        self.center_lyrics_list.addItem(empty_item2)
        
        for _, lyric_text in sorted_lyrics:
            if lyric_text.strip():
                item = QListWidgetItem(lyric_text.strip())
                # 设置列表项文本水平居中
                item.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
                self.center_lyrics_list.addItem(item)
            else:
                # 如果是空行，添加一个空格确保项目高度正确
                empty_item = QListWidgetItem(" ")
                empty_item.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
                self.center_lyrics_list.addItem(empty_item)
        
        empty_item3 = QListWidgetItem("")
        empty_item3.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
        self.center_lyrics_list.addItem(empty_item3)
        
        empty_item4 = QListWidgetItem("")
        empty_item4.setTextAlignment(int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter))
        self.center_lyrics_list.addItem(empty_item4)
        
        # 只有在当前歌词索引有效时才更新高亮
        if self.current_lyric_index >= 0:
            self.update_center_lyric_highlight(self.current_lyric_index)
    
    def update_center_lyric_highlight(self, index):
        """更新中央歌词高亮显示"""
        # 确保中央歌词组件已创建
        if not hasattr(self, 'center_lyrics_list') or not self.center_lyrics_widget.isVisible():
            return
            
        # 调整索引（因为前面添加了空行）
        adjusted_index = index + 2
        
        # 检查索引有效性
        if adjusted_index < 0 or adjusted_index >= self.center_lyrics_list.count():
            return
            
        # 清除所有选择
        self.center_lyrics_list.clearSelection()
        
        # 设置当前歌词为选中状态
        self.center_lyrics_list.setCurrentRow(adjusted_index)
        
        # 确保当前歌词在可见区域的中央
        self.center_lyrics_list.scrollToItem(
            self.center_lyrics_list.item(adjusted_index),
            QListWidget.ScrollHint.PositionAtCenter
        )

    def toggle_cover_lyrics_display(self, checked):
        """切换封面和歌词显示"""
        if checked:
            # 切换到显示封面
            self.display_center_lyrics(False)
            self.image_label.setVisible(True)
            # 如果当前有音乐文件，重新调整封面大小以适应当前窗口
            if self.current_file:
                self.display_audio_cover(self.current_file)
            self.statusBar.showMessage("已切换到封面显示", 2000)
        else:
            # 切换到显示歌词
            self.display_center_lyrics(True)
            self.image_label.setVisible(False)
            # 显示快捷键提示
            self.statusBar.showMessage("已切换到歌词显示。提示：按住Ctrl并滚动鼠标滚轮可调整歌词大小，Ctrl+0可恢复默认大小", 5000)

    def on_lyric_double_clicked(self, item):
        """中央歌词区域双击事件处理"""
        # 如果没有时间标签的歌词，无法跳转
        if not self.timed_lyrics:
            self.statusBar.showMessage("当前歌词无时间标签，无法跳转", 2000)
            return
            
        # 获取双击的歌词索引（考虑到前面添加的空行）
        index = self.center_lyrics_list.row(item) - 2
        
        # 确保索引有效
        if index < 0:
            return
            
        # 从timed_lyrics中获取对应的时间点
        sorted_lyrics = sorted(self.timed_lyrics.items())
        
        # 确保索引在有效范围内
        if index >= len(sorted_lyrics):
            return
            
        # 获取对应时间点并跳转
        time_position = sorted_lyrics[index][0]  # 获取时间(ms)
        
        # 设置音乐播放位置
        self.media_player.setPosition(time_position)
        
        # 如果当前未播放，则开始播放
        if not self.is_playing:
            self.media_player.play()
            self.is_playing = True
            self.play_btn.setText("暂停")
            
        # 显示提示消息
        self.statusBar.showMessage(f"已跳转到 {self.format_duration(time_position)}", 2000)
        
    def on_sidebar_lyric_double_clicked(self, item):
        """侧边栏歌词双击事件处理"""
        # 如果没有时间标签的歌词，无法跳转
        if not self.timed_lyrics:
            self.statusBar.showMessage("当前歌词无时间标签，无法跳转", 2000)
            return
            
        # 获取双击的歌词索引（侧边栏没有添加空行）
        index = self.lyrics_list.row(item)
        
        # 确保索引有效
        if index < 0:
            return
            
        # 从timed_lyrics中获取对应的时间点
        sorted_lyrics = sorted(self.timed_lyrics.items())
        
        # 确保索引在有效范围内
        if index >= len(sorted_lyrics):
            return
            
        # 获取对应时间点并跳转
        time_position = sorted_lyrics[index][0]  # 获取时间(ms)
        
        # 设置音乐播放位置
        self.media_player.setPosition(time_position)
        
        # 如果当前未播放，则开始播放
        if not self.is_playing:
            self.media_player.play()
            self.is_playing = True
            self.play_btn.setText("暂停")
            
        # 显示提示消息
        self.statusBar.showMessage(f"已跳转到 {self.format_duration(time_position)}", 2000)

    def update_center_lyrics_font_size(self):
        """更新中央歌词字体大小"""
        # 确保中央歌词组件已创建
        if not hasattr(self, 'center_lyrics_list'):
            return
            
        # 设置新的样式表
        self.center_lyrics_list.setStyleSheet(f"""
            QListWidget {{
                border: none;
                background-color: transparent;
                font-family: 'Microsoft YaHei', Arial;
                font-size: {self.center_lyrics_font_size}px;
                line-height: 2.0;
            }}
            QListWidget::item {{
                padding: 8px;
                border: none;
                background-color: transparent;
                text-align: center;
            }}
            QListWidget::item:selected {{
                background-color: rgba(25, 118, 210, 0.1);
                border-radius: 8px;
                color: #1976D2;
                font-size: {self.center_lyrics_font_size + 4}px;
                font-weight: bold;
            }}
        """)
        
        # 显示当前字体大小的提示信息
        self.statusBar.showMessage(f"歌词字体大小: {self.center_lyrics_font_size}px", 2000)

    def toggle_desktop_lyrics(self, checked):
        """切换桌面歌词显示"""
        try:
            self.desktop_lyric_enabled = checked
            if checked:
                self.desktop_lyric_btn.setText("隐藏桌面歌词")
                # 先确保桌面歌词窗口已正确初始化
                if not hasattr(self, 'desktop_lyric_window') or self.desktop_lyric_window is None:
                    self.desktop_lyric_window = DesktopLyricWindow()  # 不传入parent参数
                
                # 显示桌面歌词窗口
                self.desktop_lyric_window.show()
                
                # 如果当前有歌词，立即更新显示
                if hasattr(self, 'timed_lyrics') and self.timed_lyrics and self.current_lyric_index >= 0:
                    sorted_lyrics = sorted(self.timed_lyrics.items())
                    if 0 <= self.current_lyric_index < len(sorted_lyrics):
                        current_lyric = sorted_lyrics[self.current_lyric_index][1]
                        
                        # 获取下一句歌词
                        next_lyric = ""
                        if self.current_lyric_index + 1 < len(sorted_lyrics):
                            next_lyric = sorted_lyrics[self.current_lyric_index + 1][1]
                        
                        # 更新桌面歌词
                        self.desktop_lyric_window.update_lyric(current_lyric, next_lyric)
                    else:
                        # 索引超出范围，显示一个默认消息
                        self.desktop_lyric_window.update_lyric("正在播放...", "")
                else:
                    # 没有歌词或未初始化，显示一个默认消息
                    self.desktop_lyric_window.update_lyric("正在播放...", "")
            else:
                self.desktop_lyric_btn.setText("显示桌面歌词")
                if hasattr(self, 'desktop_lyric_window') and self.desktop_lyric_window is not None:
                    self.desktop_lyric_window.hide()
            
            # 显示提示信息
            if checked:
                self.statusBar.showMessage("桌面歌词已启用，可拖动调整位置", 3000)
            else:
                self.statusBar.showMessage("桌面歌词已关闭", 2000)
        except Exception as e:
            # 发生异常时，禁用桌面歌词并显示错误信息
            self.desktop_lyric_enabled = False
            if hasattr(self, 'desktop_lyric_btn'):
                self.desktop_lyric_btn.setChecked(False)
                self.desktop_lyric_btn.setText("显示桌面歌词")
            
            # 在状态栏显示错误信息
            self.statusBar.showMessage(f"桌面歌词启动失败: {str(e)}", 5000)
            
            # 如果有异常，确保窗口被隐藏
            if hasattr(self, 'desktop_lyric_window') and self.desktop_lyric_window is not None:
                try:
                    self.desktop_lyric_window.hide()
                except:
                    pass

    def insert_time_tag(self):
        """在当前光标位置插入时间标签"""
        if not hasattr(self, 'media_player') or not self.media_player.isPlaying():
            QMessageBox.warning(self, "警告", "请先播放音乐才能插入时间标签")
            return
            
        # 获取当前播放位置
        position = self.media_player.position() + self.time_offset_spinbox.value()
        if position < 0:
            position = 0
            
        minutes = position // 60000
        seconds = (position % 60000) // 1000
        milliseconds = (position % 1000) // 10
        
        # 格式化为 [mm:ss.xx]
        time_tag = f"[{minutes:02d}:{seconds:02d}.{milliseconds:02d}]"
        
        # 插入到当前光标位置
        cursor = self.lyrics_editor.textCursor()
        cursor.insertText(time_tag)
        
        # 更新当前歌词同步状态提示
        self.update_sync_status(position)

    def toggle_sync_mode(self, checked):
        """切换同步模式"""
        # 如果要启用同步模式，首先检查音乐是否在播放
        if checked and (not hasattr(self, 'media_player') or not self.media_player.isPlaying()):
            QMessageBox.warning(self, "警告", "请先播放音乐才能启用同步模式")
            # 恢复按钮状态
            self.sync_lyrics_btn.setChecked(False)
            return
            
        # 设置歌词编辑器的同步模式状态
        if hasattr(self, 'lyrics_editor') and isinstance(self.lyrics_editor, LyricTextEdit):
            self.lyrics_editor.set_sync_mode(checked)
        
        if checked:
            # 启用同步模式
            self.sync_info_label.setText("同步模式已开启 - 按空格键添加时间标签")
            self.sync_info_label.setStyleSheet("""
                QLabel {
                    background-color: #e6f7ff;
                    border: 1px solid #91d5ff;
                    border-radius: 3px;
                    padding: 5px;
                    font-weight: bold;
                    color: #1890ff;
                }
            """)
            self.sync_info_label.setVisible(True)
            
            # 确保初始状态显示正确的时间
            if hasattr(self, 'media_player'):
                current_position = self.media_player.position()
                # 使用延时更新，避免阻塞UI
                QTimer.singleShot(10, lambda: self.update_sync_status(current_position))
            
            # 焦点设置到歌词编辑器，方便用户继续编辑
            if hasattr(self, 'lyrics_editor'):
                QTimer.singleShot(100, self.lyrics_editor.setFocus)
        else:
            # 关闭同步模式
            self.sync_info_label.setText("同步模式已关闭")
            self.sync_info_label.setStyleSheet("""
                QLabel {
                    background-color: #f8f8f8;
                    border: 1px solid #ddd;
                    border-radius: 3px;
                    padding: 5px;
                    font-weight: bold;
                    color: #666;
                }
            """)
            self.sync_info_label.setVisible(False)

    def update_sync_status(self, position):
        """更新同步状态显示"""
        if not self.sync_lyrics_btn.isChecked():
            return
            
        # 添加更新频率限制，避免频繁更新导致界面卡顿
        # 使用防抖动技术，只在时间变化时更新显示
        if hasattr(self, 'last_sync_update_time'):
            # 只有当秒数变化时才更新显示，减少更新频率
            last_seconds = self.last_sync_update_time // 1000
            current_seconds = position // 1000
            
            if last_seconds == current_seconds and abs(position - self.last_sync_update_time) < 200:
                # 如果秒数相同且时差小于200毫秒，不更新
                return
                
        # 记录本次更新时间
        self.last_sync_update_time = position
            
        # 格式化当前时间
        minutes = position // 60000
        seconds = (position % 60000) // 1000
        milliseconds = (position % 1000) // 10
        
        time_str = f"{minutes:02d}:{seconds:02d}.{milliseconds:02d}"
        
        # 使用QTimer延迟更新UI，避免阻塞主线程
        QTimer.singleShot(5, lambda: self._update_sync_display(time_str))
    
    def _update_sync_display(self, time_str):
        """实际更新同步显示的辅助方法"""
        if not hasattr(self, 'sync_info_label') or not self.sync_info_label.isVisible():
            return
            
        # 更新提示文本，突出显示当前时间
        self.sync_info_label.setText(f"当前位置: <b style='color:#1890ff;'>{time_str}</b> - 按空格键添加标签，回车键换行并添加")
        
        # 不要在每次更新时强制设置焦点，这会打断用户操作
        # 只有在同步模式初次开启时才设置焦点

    def sync_mode_key_press_event(self, event):
        """同步模式下的键盘事件处理
        
        注意: 此方法已被LyricTextEdit类中的keyPressEvent方法取代，
        保留此方法仅作为参考和文档说明。对于焦点在歌词编辑器中的事件，
        现在由LyricTextEdit类直接处理。
        """
        # 检查是否为空格键
        if event.key() == Qt.Key.Key_Space and self.sync_lyrics_btn.isChecked():
            # 阻止默认空格键行为
            event.accept()
            
            # 插入时间标签
            self.insert_time_tag()
            
            # 将光标移动到行尾
            cursor = self.lyrics_editor.textCursor()
            cursor.movePosition(QTextCursor.MoveOperation.EndOfLine)
            self.lyrics_editor.setTextCursor(cursor)
            
            return
            
        # 检查是否为回车键，用于快速添加新行并带时间标签
        if event.key() == Qt.Key.Key_Return and self.sync_lyrics_btn.isChecked():
            # 阻止默认回车键行为
            event.accept()
            
            # 将光标移动到行尾
            cursor = self.lyrics_editor.textCursor()
            cursor.movePosition(QTextCursor.MoveOperation.EndOfLine)
            self.lyrics_editor.setTextCursor(cursor)
            
            # 插入换行
            cursor.insertText("\n")
            
            # 在新行插入时间标签
            self.insert_time_tag()
            
            return
            
        # 对于其他键，调用原始的事件处理函数
        if hasattr(self, 'original_key_press_event'):
            self.original_key_press_event(event)
        else:
            super().keyPressEvent(event)

    def format_lyrics(self):
        """格式化歌词，整理成标准LRC格式"""
        lyrics_text = self.lyrics_editor.toPlainText()
        
        # 提取所有时间标签
        time_pattern = re.compile(r'\[(\d{2}):(\d{2})(\.\d{2})?\]')
        
        formatted_lines = []
        for line in lyrics_text.split('\n'):
            line = line.strip()
            if not line:
                continue
                
            # 检查是否包含时间标签
            if time_pattern.search(line):
                # 提取所有时间标签和歌词文本
                tags = time_pattern.findall(line)
                text = time_pattern.sub('', line).strip()
                
                if tags and text:
                    # 为每个时间标签创建一行
                    for tag in tags:
                        minutes = tag[0]
                        seconds = tag[1]
                        milliseconds = tag[2][1:] if tag[2] else "00"
                        time_tag = f"[{minutes}:{seconds}.{milliseconds}]"
                        formatted_lines.append(f"{time_tag} {text}")
            else:
                # 如果没有时间标签但有歌词内容，保留原文本
                formatted_lines.append(line)
        
        # 更新编辑器内容
        self.lyrics_editor.setText('\n'.join(formatted_lines))
        
        # 显示格式化完成消息
        self.statusBar.showMessage("歌词格式化完成", 3000)

    def auto_tag_lines(self):
        """自动为没有时间标签的行添加时间标签"""
        if not hasattr(self, 'media_player') or self.media_player.duration() <= 0:
            QMessageBox.warning(self, "警告", "请先加载并播放音乐文件")
            return
            
        lyrics_text = self.lyrics_editor.toPlainText()
        time_pattern = re.compile(r'\[(\d{2}):(\d{2})(\.\d{2})?\]')
        
        # 计算歌曲总时长
        total_duration = self.media_player.duration()
        
        # 获取没有时间标签的行
        untagged_lines = []
        for line in lyrics_text.split('\n'):
            line = line.strip()
            if line and not time_pattern.search(line):
                untagged_lines.append(line)
                
        if not untagged_lines:
            QMessageBox.information(self, "提示", "没有找到需要添加时间标签的行")
            return
            
        # 询问用户是否要自动添加时间标签
        reply = QMessageBox.question(
            self,
            "自动添加时间标签",
            f"发现{len(untagged_lines)}行没有时间标签，是否自动添加？\n\n注意：这将基于歌曲总时长均匀分配时间，可能与实际歌词不同步。",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            # 计算时间间隔
            interval = total_duration / (len(untagged_lines) + 1)
            
            # 添加时间标签
            tagged_lines = []
            for i, line in enumerate(untagged_lines):
                position = int((i + 1) * interval)
                minutes = position // 60000
                seconds = (position % 60000) // 1000
                milliseconds = (position % 1000) // 10
                
                time_tag = f"[{minutes:02d}:{seconds:02d}.{milliseconds:02d}]"
                tagged_lines.append(f"{time_tag} {line}")
                
            # 更新编辑器内容，保留原有的带标签行
            new_lines = []
            for line in lyrics_text.split('\n'):
                line = line.strip()
                if not line:
                    continue
                if time_pattern.search(line):
                    new_lines.append(line)
                    
            # 添加新标记的行
            new_lines.extend(tagged_lines)
            
            # 按时间排序
            def extract_time(line):
                match = time_pattern.search(line)
                if match:
                    groups = match.groups()
                    minutes = int(groups[0])
                    seconds = int(groups[1])
                    milliseconds = int(groups[2][1:]) if groups[2] else 0
                    return minutes * 60000 + seconds * 1000 + milliseconds * 10
                return float('inf')
                
            new_lines.sort(key=extract_time)
            
            # 更新编辑器内容
            self.lyrics_editor.setText('\n'.join(new_lines))
            
            # 显示完成消息
            self.statusBar.showMessage(f"已自动为{len(untagged_lines)}行添加时间标签", 3000)

    def show_batch_adjust_dialog(self):
        """显示批量调整时间标签对话框"""
        if not hasattr(self, 'batch_adjust_dialog'):
            self.batch_adjust_dialog = QDialog(self)
            self.batch_adjust_dialog.setWindowTitle("批量调整时间标签")
            self.batch_adjust_dialog.setFixedSize(300, 200)
            
            layout = QVBoxLayout()
            
            # 添加时间偏移输入框
            self.time_offset_label = QLabel("时间偏移:")
            layout.addWidget(self.time_offset_label)
            
            self.time_offset_spinbox = QSpinBox()
            self.time_offset_spinbox.setRange(-5000, 5000)  # 允许 -5秒 到 +5秒
            self.time_offset_spinbox.setValue(0)
            self.time_offset_spinbox.setSingleStep(100)
            self.time_offset_spinbox.setSuffix(" ms")
            self.time_offset_spinbox.setToolTip("调整插入的时间标签偏移量")
            layout.addWidget(self.time_offset_spinbox)
            
            # 添加应用按钮
            self.apply_btn = QPushButton("应用")
            self.apply_btn.clicked.connect(self.apply_time_offset)
            layout.addWidget(self.apply_btn)
            
            self.batch_adjust_dialog.setLayout(layout)
        
        self.batch_adjust_dialog.show()

    def apply_time_offset(self):
        """应用时间偏移"""
        offset = self.time_offset_spinbox.value()
        
        # 获取当前编辑的歌词文本
        lyrics_text = self.lyrics_editor.toPlainText()
        
        # 应用偏移量调整时间标签
        adjusted_lyrics = self.adjust_time_tags(lyrics_text, offset)
        
        # 更新编辑器内容
        self.lyrics_editor.setText(adjusted_lyrics)
        
        # 关闭对话框
        self.batch_adjust_dialog.close()
        
        # 显示消息
        self.statusBar.showMessage(f"已应用时间偏移: {offset} ms", 3000)

    def adjust_time_tags(self, lyrics_text, offset_ms):
        """调整歌词中的所有时间标签
        
        Args:
            lyrics_text: 歌词文本
            offset_ms: 偏移量(毫秒)
            
        Returns:
            str: 调整后的歌词文本
        """
        if not lyrics_text:
            return ""
            
        # 找出所有时间标签 [mm:ss.xx]
        time_pattern = re.compile(r'\[(\d{2}):(\d{2})\.(\d{2})\]')
        
        def replace_time_tag(match):
            minutes = int(match.group(1))
            seconds = int(match.group(2))
            milliseconds = int(match.group(3)) * 10  # xx -> xxx
            
            # 转换为总毫秒数
            total_ms = minutes * 60 * 1000 + seconds * 1000 + milliseconds
            
            # 应用偏移
            adjusted_ms = total_ms + offset_ms
            if adjusted_ms < 0:
                adjusted_ms = 0
                
            # 转换回分钟:秒.毫秒格式
            adj_minutes = adjusted_ms // 60000
            adj_seconds = (adjusted_ms % 60000) // 1000
            adj_milliseconds = (adjusted_ms % 1000) // 10
            
            # 返回新的时间标签
            return f"[{adj_minutes:02d}:{adj_seconds:02d}.{adj_milliseconds:02d}]"
            
        # 替换所有时间标签
        adjusted_lyrics = time_pattern.sub(replace_time_tag, lyrics_text)
        
        return adjusted_lyrics

    def show_lyrics_help(self):
        """显示歌词编辑帮助"""
        help_text = """
        <h2>LRC歌词编辑使用指南</h2>
        
        <h3>基本操作：</h3>
        <ul>
            <li><b>插入时间标签</b>：点击"插入时间标签"按钮在当前光标位置插入当前播放时间的时间标签 [mm:ss.xx]</li>
            <li><b>同步模式</b>：开启后，可通过空格键快速插入时间标签，按回车键自动换行并插入新标签</li>
            <li><b>时间偏移</b>：设置时间标签的偏移量，可以微调时间标签的准确性</li>
            <li><b>格式化歌词</b>：整理歌词格式，确保每行歌词都有正确的时间标签格式</li>
            <li><b>自动标记行</b>：自动为没有时间标签的行添加均匀分布的时间标签</li>
            <li><b>批量调整</b>：对所有时间标签进行统一的时间偏移调整</li>
        </ul>
        
        <h3>快捷键（同步模式下）：</h3>
        <ul>
            <li><b>空格键</b>：在当前位置插入时间标签</li>
            <li><b>回车键</b>：换行并自动在新行插入当前时间标签</li>
        </ul>
        
        <h3>LRC歌词格式说明：</h3>
        <p>LRC歌词使用时间标签 [mm:ss.xx] 标记每句歌词的开始时间：</p>
        <pre>
        [00:12.34] 这是一句歌词
        [00:18.56] 这是下一句歌词
        </pre>
        
        <p>您也可以添加歌曲信息标签：</p>
        <pre>
        [ti:歌曲名]
        [ar:艺术家]
        [al:专辑名]
        [by:制作者]
        </pre>
        """
        
        # 创建对话框显示帮助内容
        help_dialog = QDialog(self)
        help_dialog.setWindowTitle("歌词编辑帮助")
        help_dialog.resize(500, 500)
        
        layout = QVBoxLayout()
        
        # 添加帮助文本
        help_label = QLabel(help_text)
        help_label.setTextFormat(Qt.TextFormat.RichText)
        help_label.setWordWrap(True)
        help_label.setOpenExternalLinks(True)
        
        # 添加滚动区域
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setWidget(help_label)
        layout.addWidget(scroll_area)
        
        # 添加关闭按钮
        close_button = QPushButton("关闭")
        close_button.clicked.connect(help_dialog.close)
        layout.addWidget(close_button)
        
        help_dialog.setLayout(layout)
        help_dialog.exec()

    def set_audio_cover(self):
        """设置音乐封面"""
        if not self.current_file:
            QMessageBox.warning(self, "警告", "请先打开音乐文件")
            return
            
        # 创建上下文菜单
        menu = QMenu()
        
        # 选择图片文件作为封面
        select_cover_action = QAction("选择图片作为封面")
        select_cover_action.triggered.connect(self.select_cover_image)
        menu.addAction(select_cover_action)
        
        # 切换到默认封面
        default_cover_action = QAction("使用默认封面")
        default_cover_action.triggered.connect(lambda: self.display_audio_cover(self.current_file))
        menu.addAction(default_cover_action)
        
        # 切换显示封面/歌词
        if hasattr(self, 'center_lyrics_widget') and self.center_lyrics_widget.isVisible():
            show_cover_action = QAction("显示封面")
            show_cover_action.triggered.connect(lambda: self.toggle_cover_lyrics_display(True))
            menu.addAction(show_cover_action)
        else:
            show_lyrics_action = QAction("显示歌词")
            show_lyrics_action.triggered.connect(lambda: self.toggle_cover_lyrics_display(False))
            menu.addAction(show_lyrics_action)
        
        # 显示菜单
        menu.exec(self.mapToGlobal(self.toggle_cover_btn.pos()))
        
    def select_cover_image(self):
        """选择图片作为封面"""
        if not self.current_file:
            return
            
        # 打开文件选择对话框
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            "选择封面图片",
            "",
            "图片文件 (*.jpg *.jpeg *.png *.bmp *.gif);;所有文件 (*)"
        )
        
        if not file_path:
            return
            
        try:
            # 加载图片
            pixmap = QPixmap(file_path)
            
            # 如果图片加载成功，缩放并设置为封面
            if not pixmap.isNull():
                # 获取预览区域的大小
                preview_size = self.preview_area.size()
                available_width = preview_size.width() - 20  # 减去一些边距
                available_height = preview_size.height() - 20  # 减去一些边距
                
                # 确保至少有一个最小尺寸
                if available_width < 200:
                    available_width = 200
                if available_height < 200:
                    available_height = 200
                
                # 缩放图片以适应显示区域，保持纵横比
                pixmap = pixmap.scaled(
                    available_width, available_height,
                    Qt.AspectRatioMode.KeepAspectRatio,
                    Qt.TransformationMode.SmoothTransformation
                )
                
                # 设置图片到标签
                self.image_label.setPixmap(pixmap)
                
                # 将图片居中显示
                self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
                
                # 设置图片标签的大小策略，使其能够占满可用空间
                from PyQt6.QtWidgets import QSizePolicy
                self.image_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
                
                # 保存自定义封面路径到文件状态
                self.file_states[self.current_file]['custom_cover'] = file_path
                self.save_file_state(self.current_file)
                
                # 显示封面
                self.image_label.setVisible(True)
                if hasattr(self, 'center_lyrics_widget'):
                    self.center_lyrics_widget.setVisible(False)
                
                # 显示提示消息
                self.statusBar.showMessage(f"已设置自定义封面: {os.path.basename(file_path)}", 3000)
            else:
                QMessageBox.warning(self, "错误", "无法加载选定的图片")
        except Exception as e:
            QMessageBox.warning(self, "错误", f"设置封面时出错: {str(e)}")

    # 新增菜单方法实现
    def open_folder(self):
        """打开文件夹"""
        folder_path = QFileDialog.getExistingDirectory(self, "选择文件夹")
        if folder_path:
            # 可以在这里实现文件夹浏览功能
            QMessageBox.information(self, "提示", f"已选择文件夹: {folder_path}")
    
    def zoom_reset(self):
        """重置缩放"""
        self.current_zoom = 100
        self.update_zoom_display()
    
    def fit_to_window(self):
        """适应窗口"""
        if self.image_label.isVisible():
            # 对于图片，适应窗口大小
            self.fit_image_to_window()
        elif self.pdf_doc:
            # 对于PDF，适应页面宽度
            self.fit_pdf_to_window()
    
    def fit_image_to_window(self):
        """图片适应窗口"""
        if hasattr(self, 'original_pixmap') and self.original_pixmap:
            # 获取显示区域大小
            available_size = self.scroll_area.viewport().size()
            # 计算缩放比例
            scale_x = available_size.width() / self.original_pixmap.width()
            scale_y = available_size.height() / self.original_pixmap.height()
            scale = min(scale_x, scale_y) * 100
            self.current_zoom = int(scale)
            self.update_zoom_display()
    
    def fit_pdf_to_window(self):
        """PDF适应窗口"""
        if self.pdf_doc and self.current_page < len(self.page_images):
            # 获取显示区域大小
            available_size = self.scroll_area.viewport().size()
            # 重新渲染当前页面以适应窗口
            self.render_pdf_page(self.current_page, fit_width=True)
    
    def toggle_play_pause(self):
        """播放/暂停切换"""
        if hasattr(self, 'media_player') and self.media_player:
            if self.media_player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
                self.media_player.pause()
            else:
                self.media_player.play()
    
    def stop_media(self):
        """停止媒体播放"""
        if hasattr(self, 'media_player') and self.media_player:
            self.media_player.stop()
    
    def previous_media(self):
        """上一个媒体"""
        if hasattr(self, 'playlist') and self.playlist:
            self.play_previous()
    
    def next_media(self):
        """下一个媒体"""
        if hasattr(self, 'playlist') and self.playlist:
            self.play_next()
    
    def volume_up(self):
        """音量增加"""
        if hasattr(self, 'volume_slider') and self.volume_slider:
            current_volume = self.volume_slider.value()
            new_volume = min(100, current_volume + 10)
            self.volume_slider.setValue(new_volume)
    
    def volume_down(self):
        """音量减少"""
        if hasattr(self, 'volume_slider') and self.volume_slider:
            current_volume = self.volume_slider.value()
            new_volume = max(0, current_volume - 10)
            self.volume_slider.setValue(new_volume)
    
    def toggle_mute(self):
        """静音切换"""
        if hasattr(self, 'audio_output') and self.audio_output:
            self.audio_output.setMuted(not self.audio_output.isMuted())
    
    def toggle_desktop_lyric(self, checked):
        """切换桌面歌词显示"""
        self.desktop_lyric_enabled = checked
        if checked:
            self.desktop_lyric_window.show()
        else:
            self.desktop_lyric_window.hide()
    
    def show_file_info(self):
        """显示文件信息"""
        if not self.current_file:
            QMessageBox.information(self, "文件信息", "当前没有打开的文件")
            return
        
        try:
            file_stat = os.stat(self.current_file)
            file_size = file_stat.st_size
            
            # 格式化文件大小
            if file_size < 1024:
                size_str = f"{file_size} B"
            elif file_size < 1024 * 1024:
                size_str = f"{file_size / 1024:.2f} KB"
            elif file_size < 1024 * 1024 * 1024:
                size_str = f"{file_size / (1024 * 1024):.2f} MB"
            else:
                size_str = f"{file_size / (1024 * 1024 * 1024):.2f} GB"
            
            # 获取文件时间
            import datetime
            modified_time = datetime.datetime.fromtimestamp(file_stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S')
            created_time = datetime.datetime.fromtimestamp(file_stat.st_ctime).strftime('%Y-%m-%d %H:%M:%S')
            
            info_text = f"""文件路径: {self.current_file}
文件大小: {size_str}
修改时间: {modified_time}
创建时间: {created_time}
编码: {self.current_encoding}"""
            
            QMessageBox.information(self, "文件信息", info_text)
        except Exception as e:
            QMessageBox.warning(self, "错误", f"获取文件信息失败: {str(e)}")
    
    def convert_encoding(self, encoding):
        """转换文件编码"""
        if not self.current_file or not self.text_editor.isVisible():
            QMessageBox.warning(self, "警告", "当前没有打开的文本文件")
            return
        
        try:
            # 重新以指定编码读取文件
            with open(self.current_file, 'r', encoding=encoding) as file:
                content = file.read()
            
            self.text_editor.setPlainText(content)
            self.current_encoding = encoding
            self.statusBar.showMessage(f"已转换为 {encoding} 编码", 3000)
        except Exception as e:
            QMessageBox.warning(self, "错误", f"编码转换失败: {str(e)}")
    
    def show_settings(self):
        """显示设置对话框"""
        QMessageBox.information(self, "设置", "设置功能正在开发中...")
    
    def toggle_maximize(self):
        """最大化/还原窗口"""
        if self.isMaximized():
            self.showNormal()
            self.maximize_action.setText("最大化(&X)")
        else:
            self.showMaximized()
            self.maximize_action.setText("还原(&R)")
    
    def show_help(self):
        """显示使用说明"""
        help_text = """<h2>GoFile 使用说明</h2>
        
<h3>支持的文件类型：</h3>
<ul>
<li><b>文本文件</b>：txt, md, py, js, html, css, xml, json 等</li>
<li><b>图片文件</b>：jpg, png, gif, bmp, svg 等</li>
<li><b>PDF文件</b>：pdf</li>
<li><b>音频文件</b>：mp3, wav, flac, aac 等</li>
<li><b>视频文件</b>：mp4, avi, mkv, mov 等</li>
<li><b>Office文件</b>：docx, xlsx, pptx</li>
<li><b>电子书</b>：epub</li>
</ul>

<h3>基本操作：</h3>
<ul>
<li>拖拽文件到窗口中打开</li>
<li>使用 Ctrl+O 打开文件</li>
<li>使用 F11 切换全屏模式</li>
<li>使用鼠标滚轮缩放图片和PDF</li>
<li>支持音频播放列表和歌词显示</li>
</ul>"""
        
        msg = QMessageBox(self)
        msg.setWindowTitle("使用说明")
        msg.setTextFormat(Qt.TextFormat.RichText)
        msg.setText(help_text)
        msg.exec()
    
    def show_shortcuts(self):
        """显示快捷键列表"""
        shortcuts_text = """<h2>快捷键列表</h2>
        
<h3>文件操作：</h3>
<ul>
<li><b>Ctrl+N</b>：新建文件</li>
<li><b>Ctrl+O</b>：打开文件</li>
<li><b>Ctrl+Shift+O</b>：打开文件夹</li>
<li><b>Ctrl+S</b>：保存文件</li>
<li><b>Ctrl+Shift+S</b>：另存为</li>
<li><b>Alt+F4</b>：退出程序</li>
</ul>

<h3>编辑操作：</h3>
<ul>
<li><b>Ctrl+Z</b>：撤销</li>
<li><b>Ctrl+Y</b>：重做</li>
<li><b>Ctrl+X</b>：剪切</li>
<li><b>Ctrl+C</b>：复制</li>
<li><b>Ctrl+V</b>：粘贴</li>
<li><b>Ctrl+A</b>：全选</li>
<li><b>Ctrl+F</b>：查找</li>
<li><b>Ctrl+H</b>：替换</li>
</ul>

<h3>视图操作：</h3>
<ul>
<li><b>Ctrl+=</b>：放大</li>
<li><b>Ctrl+-</b>：缩小</li>
<li><b>Ctrl+0</b>：重置缩放</li>
<li><b>Ctrl+9</b>：适应窗口</li>
<li><b>F11</b>：全屏模式</li>
</ul>

<h3>媒体控制：</h3>
<ul>
<li><b>空格</b>：播放/暂停</li>
<li><b>Ctrl+.</b>：停止</li>
<li><b>Ctrl+Left</b>：上一个</li>
<li><b>Ctrl+Right</b>：下一个</li>
<li><b>Ctrl+Up</b>：音量增加</li>
<li><b>Ctrl+Down</b>：音量减少</li>
<li><b>M</b>：静音</li>
</ul>

<h3>窗口操作：</h3>
<ul>
<li><b>Ctrl+Shift+N</b>：新建窗口</li>
<li><b>Ctrl+M</b>：最小化</li>
</ul>

<h3>其他：</h3>
<ul>
<li><b>F1</b>：显示帮助</li>
<li><b>Alt+Enter</b>：文件信息</li>
</ul>"""
        
        msg = QMessageBox(self)
        msg.setWindowTitle("快捷键列表")
        msg.setTextFormat(Qt.TextFormat.RichText)
        msg.setText(shortcuts_text)
        msg.exec()
    
    def install_context_menu(self):
        """安装右键菜单"""
        if not self.system_integration:
            QMessageBox.warning(self, "警告", "系统集成功能不可用！")
            return
        
        try:
            if self.system_integration.install_context_menu():
                QMessageBox.information(self, "成功", "右键菜单安装成功！\n\n现在您可以在Windows资源管理器中右键点击支持的文件类型，选择'用GoFile打开'。")
                if self.system_integration:
                    self.system_integration.show_tray_message("GoFile", "右键菜单安装成功")
            else:
                QMessageBox.warning(self, "失败", "右键菜单安装失败！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"安装右键菜单时发生错误：\n{str(e)}")
    
    def uninstall_context_menu(self):
        """卸载右键菜单"""
        if not self.system_integration:
            QMessageBox.warning(self, "警告", "系统集成功能不可用！")
            return
        
        try:
            if self.system_integration.uninstall_context_menu():
                QMessageBox.information(self, "成功", "右键菜单卸载成功！")
                if self.system_integration:
                    self.system_integration.show_tray_message("GoFile", "右键菜单卸载成功")
            else:
                QMessageBox.warning(self, "失败", "右键菜单卸载失败！")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"卸载右键菜单时发生错误：\n{str(e)}")
    
    def set_file_associations(self):
        """设置文件关联"""
        if not self.system_integration:
            QMessageBox.warning(self, "警告", "系统集成功能不可用！")
            return
        
        reply = QMessageBox.question(
            self, 
            "确认", 
            "是否将GoFile设置为支持文件类型的默认程序？\n\n这将允许您双击文件直接用GoFile打开。",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            try:
                if self.system_integration.set_file_associations():
                    QMessageBox.information(self, "成功", "文件关联设置成功！\n\n现在您可以双击支持的文件类型直接用GoFile打开。")
                    if self.system_integration:
                        self.system_integration.show_tray_message("GoFile", "文件关联设置成功")
                else:
                    QMessageBox.warning(self, "失败", "文件关联设置失败！")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"设置文件关联时发生错误：\n{str(e)}")
    
    def remove_file_associations(self):
        """移除文件关联"""
        if not self.system_integration:
            QMessageBox.warning(self, "警告", "系统集成功能不可用！")
            return
        
        reply = QMessageBox.question(
            self, 
            "确认", 
            "是否移除GoFile的文件关联？\n\n这将从系统中移除GoFile作为默认程序的设置。",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            try:
                if self.system_integration.remove_file_associations():
                    QMessageBox.information(self, "成功", "文件关联移除成功！")
                    if self.system_integration:
                        self.system_integration.show_tray_message("GoFile", "文件关联移除成功")
                else:
                    QMessageBox.warning(self, "失败", "文件关联移除失败！")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"移除文件关联时发生错误：\n{str(e)}")
    
    def force_quit(self):
        """强制退出应用程序"""
        self._force_close = True
        self.close()
    
    def check_updates(self):
        """检查更新"""
        QMessageBox.information(self, "检查更新", "当前版本已是最新版本！")
    
    def show_about(self):
        """显示关于对话框"""
    
    def show_theme_settings(self):
        """显示主题设置对话框"""
        if not self.theme_system:
            QMessageBox.warning(self, "警告", "主题系统不可用！")
            return
        
        # 创建主题设置对话框
        dialog = self.theme_system.create_theme_dialog()
        if dialog:
            dialog.exec()
    
    def show_layout_settings(self):
        """显示布局设置对话框"""
        if not self.layout_manager:
            QMessageBox.warning(self, "警告", "布局管理器不可用！")
            return
        
        # 创建布局设置对话框
        dialog = self.layout_manager.create_layout_dialog()
        if dialog:
            dialog.exec()
    
    def show_toolbar_settings(self):
        """显示工具栏设置对话框"""
        if not self.toolbar_manager:
            QMessageBox.warning(self, "警告", "工具栏管理器不可用！")
            return
        
        # 创建工具栏设置对话框
        dialog = self.toolbar_manager.create_toolbar_dialog()
        if dialog:
            dialog.exec()
        about_text = """<h2>关于 GoFile</h2>
        
<p><b>版本：</b>1.0.0</p>
<p><b>描述：</b>一个功能强大的多媒体文件查看器</p>

<h3>主要功能：</h3>
<ul>
<li>支持多种文件格式的查看和编辑</li>
<li>音频播放和歌词显示</li>
<li>视频播放</li>
<li>PDF和电子书阅读</li>
<li>图片查看和基本编辑</li>
<li>Office文档预览</li>
</ul>

<p><b>开发者：</b>GoFile Team</p>
<p><b>技术栈：</b>Python + PyQt6</p>

<p>感谢您使用 GoFile！</p>"""
        
        msg = QMessageBox(self)
        msg.setWindowTitle("关于 GoFile")
        msg.setTextFormat(Qt.TextFormat.RichText)
        msg.setText(about_text)
        msg.exec()

def main():
    """应用程序入口函数"""
    app = QApplication(sys.argv)
    
    # 初始化全局窗口列表
    global all_windows
    all_windows = []
    
    # 连接lastWindowClosed信号，当所有窗口都关闭时退出应用程序
    app.lastWindowClosed.connect(app.quit)
    
    # 分析命令行参数，如果提供了文件路径，则打开该文件
    if len(sys.argv) > 1:
        file_path = sys.argv[1]
        window = MainWindow(file_path)
    else:
        window = MainWindow()
    
    # 添加窗口到全局列表
    all_windows.append(window)
    
    window.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()

# 访问 https://www.jetbrains.com/help/pycharm/ 获取 PyCharm 帮助
